如何在mgo中取消引用dbref?

ben*_*nyu 9 go mgo

var (
    type User struct{
        Id bson.ObjectId `bson:"_id"`
        Name string
    }

type Post struct{
    Id bson.ObjectId `bson:"_id"`
    Uid string
    User User
    ref mgo.DBRef
    Title string
    }
)
Run Code Online (Sandbox Code Playgroud)

//尝试10000次插入

id := bson.NewObjectId()
user := &User{ id, "test"}
db.C("users").insert(user)

post := db.C("Post").insert(&Post{Uid: id.hex(), ref: mgo.DBRef{"ref":"users", "id": id}, Title:"test dbref"})
Run Code Online (Sandbox Code Playgroud)

//第一道这么脏-_-!

// mysql:在user.id = post.uid上加入用户,在mgo中怎么做?

posts := new([]User)
db.C("posts").Find(nil).All(posts)

ids := []bson.ObjectId
for _, p := range posts{
  ids = append(ids, p.Uid)
}

users := make([]User, len(ids))
db.C("users").Find(bson.M{"_id": {"$in": ids}}).All(users)

//and then set the User attribute?
for _,u := range users {
   for _, m := range m{
       if m.Uid == u.Id {
          m.User = m
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

第二种方式,有ref属性,但mgo.session会尝试findid

for _,m := range posts{
   db.FindRef(m.ref).One(&m.User)
}
Run Code Online (Sandbox Code Playgroud)

//第3种方式,用mapReduce ??

这是我的第一个golang + mongodb,那么归档dbref或join的最佳方法是什么?

谢谢

Wan*_*iar 3

您可以不使用DBRef ,而是使用手动引用方法来连接两个或多个相关文档。例如,您的结构可以如下所示:

type User struct{
    Id bson.ObjectId `bson:"_id"`
    Name string `json:"name"`
}

type Post struct{
    UserId bson.ObjectId `json:"userid"` // manual ref to User
    Title string
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用$lookup 聚合阶段来执行左外连接。例如,要根据用户查找所有帖子:

pipeline := []bson.M{ 
        bson.M{"$lookup": bson.M{
                            "from": "posts", 
                            "foreignField":"userid",
                            "localField":"_id",
                            "as":"posts",
                            },
              },
        }

result := []bson.M{}    
err := coll_users.Pipe(pipeline).All(&result)
Run Code Online (Sandbox Code Playgroud)

结果示例:

{
  "_id": ObjectId("590ab726f4bab950360c2dbe"),
  "name": "test",
  "posts": [
    {
      "_id": ObjectId("590ab72619663bad7743ff9e"),
      "userid": ObjectId("590ab726f4bab950360c2dbe"),
      "title": "test manual reference"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

除了将用户和帖子存储在单独的集合中之外,您还可以嵌入/子文档。另请参见数据建模