如何在mgo中取消引用dbref?

huangapple go评论102阅读模式
英文:

How to dereference dbref in mgo?

问题

以下是翻译好的内容:

  1. var (
  2. type User struct{
  3. Id bson.ObjectId `bson:"_id"`
  4. Name string
  5. }
  6. type Post struct{
  7. Id bson.ObjectId `bson:"_id"`
  8. Uid string
  9. User User
  10. ref mgo.DBRef
  11. Title string
  12. }
  13. )
  14. > //尝试插入10000次
  15. id := bson.NewObjectId()
  16. user := &User{ id, "test"}
  17. db.C("users").insert(user)
  18. post := db.C("Post").insert(&Post{Uid: id.hex(), ref: mgo.DBRef{"ref":"users", "id": id}, Title:"test dbref"})
  19. >> //第一种方式很脏 -_-!
  20. //在mgo中如何实现MySQL的左连接(left join users on user.id=post.uid)?
  21. posts := new([]User)
  22. db.C("posts").Find(nil).All(posts)
  23. ids := []bson.ObjectId
  24. for _, p := range posts{
  25. ids = append(ids, p.Uid)
  26. }
  27. users := make([]User, len(ids))
  28. db.C("users").Find(bson.M{"_id": {"$in": ids}}).All(users)
  29. //然后设置User属性?
  30. for _,u := range users {
  31. for _, m := range m{
  32. if m.Uid == u.Id {
  33. m.User = m
  34. }
  35. }
  36. }
  37. > 第二种方式使用ref属性但是mgo.session会尝试查找id
  38. for _,m := range posts{
  39. db.FindRef(m.ref).One(&m.User)
  40. }
  41. > //第三种方式,使用mapReduce??
  42. 这是我第一次使用golang + mongodb那么实现dbref或者join的最佳方式是什么
  43. 谢谢
英文:
  1. var (
  2. type User struct{
  3. Id bson.ObjectId `bson:"_id"`
  4. Name string
  5. }
  6. type Post struct{
  7. Id bson.ObjectId `bson:"_id"`
  8. Uid string
  9. User User
  10. ref mgo.DBRef
  11. Title string
  12. }
  13. )

> //try 10000 times inserts

  1. id := bson.NewObjectId()
  2. user := &User{ id, "test"}
  3. db.C("users").insert(user)
  4. post := db.C("Post").insert(&Post{Uid: id.hex(), ref: mgo.DBRef{"ref":"users", "id": id}, Title:"test dbref"})

>> //first way so dirty -_-!

//mysql: left join users on user.id=post.uid, how to do in mgo ?

  1. posts := new([]User)
  2. db.C("posts").Find(nil).All(posts)
  3. ids := []bson.ObjectId
  4. for _, p := range posts{
  5. ids = append(ids, p.Uid)
  6. }
  7. users := make([]User, len(ids))
  8. db.C("users").Find(bson.M{"_id": {"$in": ids}}).All(users)
  9. //and then set the User attribute?
  10. for _,u := range users {
  11. for _, m := range m{
  12. if m.Uid == u.Id {
  13. m.User = m
  14. }
  15. }
  16. }

> secondary way,with ref attribute, but mgo.session will try to findid

  1. for _,m := range posts{
  2. db.FindRef(m.ref).One(&m.User)
  3. }

> //3th way, with mapReduce ??

it's my first golang + mongodb, so what is the best way to archive dbref or joins?

Thx

答案1

得分: 3

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

  1. type User struct{
  2. Id bson.ObjectId `bson:"_id"`
  3. Name string `json:"name"`
  4. }
  5. type Post struct{
  6. UserId bson.ObjectId `json:"userid"` // 对User的手动引用
  7. Title string
  8. }

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

  1. pipeline := []bson.M{
  2. bson.M{"$lookup": bson.M{
  3. "from": "posts",
  4. "foreignField":"userid",
  5. "localField":"_id",
  6. "as":"posts",
  7. }},
  8. }
  9. result := []bson.M{}
  10. err := coll_users.Pipe(pipeline).All(&result)

示例结果:

  1. {
  2. "_id": ObjectId("590ab726f4bab950360c2dbe"),
  3. "name": "test",
  4. "posts": [
  5. {
  6. "_id": ObjectId("590ab72619663bad7743ff9e"),
  7. "userid": ObjectId("590ab726f4bab950360c2dbe"),
  8. "title": "test manual reference"
  9. }
  10. ]
  11. }

除了将用户和帖子存储在单独的集合中,你还可以选择嵌入/子文档的方式。详见数据建模

英文:

Instead of using DBRef, you can just use manual reference method for connecting two or more related documents. For example your struct can just look as below:

  1. type User struct{
  2. Id bson.ObjectId `bson:"_id"`
  3. Name string `json:"name"`
  4. }
  5. type Post struct{
  6. UserId bson.ObjectId `json:"userid"` // manual ref to User
  7. Title string
  8. }

You can then use $lookup aggregation stage to perform a left outer join. For example, to find out all posts based on users:

  1. pipeline := []bson.M{
  2. bson.M{"$lookup": bson.M{
  3. "from": "posts",
  4. "foreignField":"userid",
  5. "localField":"_id",
  6. "as":"posts",
  7. },
  8. },
  9. }
  10. result := []bson.M{}
  11. err := coll_users.Pipe(pipeline).All(&result)

Example result:

  1. {
  2. "_id": ObjectId("590ab726f4bab950360c2dbe"),
  3. "name": "test",
  4. "posts": [
  5. {
  6. "_id": ObjectId("590ab72619663bad7743ff9e"),
  7. "userid": ObjectId("590ab726f4bab950360c2dbe"),
  8. "title": "test manual reference"
  9. }
  10. ]
  11. }

Alternative to storing users and posts in separate collections, you could also embed/sub-document. See also Data Modelling

huangapple
  • 本文由 发表于 2015年8月22日 16:13:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/32153927.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定