簡體   English   中英

Golang mongodb mgo driver Upsert / UpsertId文檔

[英]Golang mongodb mgo driver Upsert / UpsertId documentation

mongodb文檔說:

如果參數僅包含更新運算符表達式,則為和參數的字段和值。 此更新根據參數中的等於子句創建基本文檔,然后應用參數中的更新表達式。

並且mgo文檔說:

Upsert查找與提供的選擇器文檔匹配的單個文檔,並根據更新文檔對其進行修改。 如果找不到與選擇器匹配的文檔,則將更新文檔應用於選擇器文檔,並將結果插入到集合中。

但如果我像這樣做一個upsert:

session.UpsertId(data.Code, data)

我最終得到一個條目,它具有由mongodb自動生成的ObjectID,而不是data.Code。

這意味着UpsertId期望使用更新運算符格式化數據,並且您不能使用任意結構? 或者我在這里失蹤了什么?

鈀。 Mongo 2.4.9 mgo v2 golang go version devel + f613443bb13a

編輯:

這是我的意思的樣本,使用Neil Lunn的示例代碼:

package main

import (
  "fmt"
  "gopkg.in/mgo.v2"
  // "gopkg.in/mgo.v2/bson"
)

type Person struct {
  Code string
  Name  string
}

func main() {
  session, err := mgo.Dial("admin:admin@localhost");

  if err != nil {
        fmt.Println("Error: ", err)
        return
    // panic(err)
  }

  defer session.Close()

  session.SetMode(mgo.Monotonic, true)

  c := session.DB("test").C("people")

  var p = Person{
    Code: "1234",
    Name: "Bill",
  }

  _, err = c.UpsertId( p.Code, &p )

  result := Person{}
  err = c.FindId(p.Code).One(&result)
  if err != nil {
        fmt.Println("FindId Error: ", err)
        return
    // panic(err)
  }

  fmt.Println("Person", result)

}

我發現MongoDB的文檔是對的。 執行此操作的正確方法是將結構包裝到插入更新運算符中。

Neil Lunn提供的示例代碼如下所示:

package main

import (
  "fmt"
  "gopkg.in/mgo.v2"
  "gopkg.in/mgo.v2/bson"
)

type Person struct {
  Code string
  Name  string
}

func main() {
  session, err := mgo.Dial("admin:admin@localhost");

  if err != nil {
        fmt.Println("Error: ", err)
        return
  }

  defer session.Close()

  session.SetMode(mgo.Monotonic, true)

  c := session.DB("test").C("people")

  var p = Person{
    Code: "1234",
    Name: "Bill",
  }
    upsertdata := bson.M{ "$set": p}

    info , err2 := c.UpsertId( p.Code, upsertdata )
    fmt.Println("UpsertId -> ", info, err2)
  result := Person{}
  err = c.FindId(p.Code).One(&result)
  if err != nil {
        fmt.Println("FindId Error: ", err)
        return
  }

  fmt.Println("Person", result)

}

非常感謝您的關注和幫助Neil。

您似乎在談論在此處為自定義_id字段分配結構。 這實際上取決於您如何定義結構。 這是一個簡單的例子:

package main

import (
  "fmt"
  "gopkg.in/mgo.v2"
  "gopkg.in/mgo.v2/bson"
)

type Person struct {
  ID    string `bson:"_id"`
  Name  string
}

func main() {
  session, err := mgo.Dial("127.0.0.1");

  if err != nil {
    panic(err)
  }

  defer session.Close()

  session.SetMode(mgo.Monotonic, true)

  c := session.DB("test").C("people")

  var p = Person{
    ID: "1",
    Name: "Bill",
  }

  _, err = c.UpsertId( p.ID, &p )

  result := Person{}
  err = c.Find(bson.M{"_id": p.ID}).One(&result)
  if err != nil {
    panic(err)
  }

  fmt.Println("Person", result)

}

所以在這里的自定義定義中,我將ID字段映射到bson _id並將其類型定義為字符串。 如示例所示,這正是通過UpsertId序列化然后檢索時發生的情況。


現在你已經詳細說明了我將指出struct定義的不同之處。

我得到的是:

{ "_id": 1, "name": "Bill" }

你有什么(在結構上沒有相同的映射)這樣做:

{ "_id": ObjectId("53cfa557e248860d16e1f7e0"), "code": 1, "name": "Bill" }

如您所見,upsert中給出的_id將永遠不會匹配,因為結構中的所有字段都不會映射到_id 你需要和我一樣:

type Person struct {
    Code string `bson:"_id"`
    Name string
}

將字段映射到強制_id字段,否則會自動為您生成一個字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM