如果参数仅包含更新运算符表达式,则参数和参数的字段和值。此更新根据参数中的equality子句创建基本文档,然后应用参数中的更新表达式。
Upsert查找与提供的选择器文档匹配的单个文档,并根据更新文档对其进行修改。如果找不到与选择器匹配的文档,则更新文档将应用于选择器文档,并将结果插入集合中。
但如果我像这样做一个upsert:
session.UpsertId(data.Code, data)
我最终得到一个条目,它有一个由mongodb自动生成的ObjectID,而不是data.Code。
这意味着UpsertId期望使用更新运算符格式化数据,并且您不能使用任意结构?或者我在这里失踪了什么?
的Pd。 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)
}
答案 0 :(得分:4)
我发现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。
答案 1 :(得分:2)
您似乎在谈论在此处为自定义_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
字段,否则会自动为您生成一个字段。