不了解mongoDB Update如何在Go中运行

时间:2016-05-06 14:18:17

标签: mongodb go mgo

我正在尝试为Go结构实现MongoDB更新。简而言之,它看起来像这样:

type MyStruct struct {
        Id     bson.ObjectId `bson:"_id"`
        Fruit string         `bson:"fruit"`
}

func TestUpdate(t *testing.T) {
        obj1 := MyStruct{Id: bson.NewObjectId(),Fruit: "apple"}
        var obj2 MyStruct

        session, _ := mgo.Dial("whatever")
        col := session.DB("test").C("collection")
        col.Insert(&obj1)
        obj1.Fruit = "cherry"
        if err := col.Update(obj1.Id, bson.M{"$set": &obj1}); err != nil {
                t.Errorf(err.Error())
        }
        if err := col.Find(bson.M{"Id": obj1.Id}).One(&obj2); err != nil {
                t.Errorf(err.Error())
        }
        if obj1.Fruit != obj2.Fruit {
                t.Errorf("Expected %s, got %s", obj1.Fruit, obj2.Fruit)
        }
}

这会生成错误消息,表明该值未更新。我错过了什么?

我知道只更新一个字段是可能的,但鉴于这是在数据层中,代码之上并没有任何MongoDB知识,因此以一般方式实现将是一项挑战。即我真的需要对Go对象进行任何更新,然后更新后备存储中对象的副本。我想我可以检索对象并做一个"差异"手动,构建" $ set"文档,但似乎每次进行更新时添加检索都非常有效。

编辑:使用" _id"尝试使用地图删除

我已尝试将代码修改为以下内容:

package testmgo

import (
    mgo "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "github.com/fatih/structs"
    "testing"
)

type MyStruct struct {
    Id     bson.ObjectId `bson:"_id"`
    Fruit string         `bson:"fruit"`
}

func TestUpdate(t *testing.T) {
    obj1 := MyStruct{Id: bson.NewObjectId(),Fruit: "apple"}
    var obj2 MyStruct

    session, _ := mgo.Dial("localhost")
    col := session.DB("test").C("collection")
    col.Insert(&obj1)
    obj1.Fruit = "cherry"
    omap := structs.Map(&obj1)
    delete(omap, "_id")

    if err := col.UpdateId(obj1.Id, bson.M{"$set": bson.M(omap)}); err != nil {
        t.Errorf(err.Error())
    }
    if err := col.Find(bson.M{"Id": obj1.Id}).One(&obj2); err != nil {
        t.Errorf(err.Error())
    }
    if obj1.Fruit != obj2.Fruit {
        t.Errorf("Expected %s, got %s", obj1.Fruit, obj2.Fruit)
    }
}

我仍然收到相同的结果(Expected cherry, got apple)。请注意,对UpdateId()的调用不会返回错误。

1 个答案:

答案 0 :(得分:0)

问题在于我使用了错误的字段作为密钥。我已将“Id”映射到“_id”,但后来要求MongoDB使用Go属性名称而不是名称来查找记录。这可以正常工作:

package testmgo

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

type MyStruct struct {
    Id    bson.ObjectId `bson:"_id"`
    Fruit string        `bson:"fruit"`
}

func TestUpdate(t *testing.T) {
    obj1 := MyStruct{Id: bson.NewObjectId(), Fruit: "apple"}
    var obj2 MyStruct

    session, _ := mgo.Dial("localhost")
    col := session.DB("test").C("collection")
    col.Insert(&obj1)
    obj1.Fruit = "cherry"

    if err := col.UpdateId(obj1.Id, bson.M{"$set": &obj1}); err != nil {
        t.Errorf(err.Error())
    }
    if err := col.Find(bson.M{"_id": obj1.Id}).One(&obj2); err != nil {
        t.Errorf(err.Error())
    }
    if obj1.Fruit != obj2.Fruit {
        t.Errorf("Expected %s, got %s", obj1.Fruit, obj2.Fruit)
    }
}