英文:
How to dereference dbref in 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
}
)
> //尝试插入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"})
>> //第一种方式很脏 -_-!
//在mgo中如何实现MySQL的左连接(left join users on user.id=post.uid)?
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)
//然后设置User属性?
for _,u := range users {
for _, m := range m{
if m.Uid == u.Id {
m.User = m
}
}
}
> 第二种方式,使用ref属性,但是mgo.session会尝试查找id
for _,m := range posts{
db.FindRef(m.ref).One(&m.User)
}
> //第三种方式,使用mapReduce??
这是我第一次使用golang + mongodb,那么实现dbref或者join的最佳方式是什么?
谢谢
英文:
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
}
)
> //try 10000 times inserts
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"})
>> //first way so dirty -_-!
//mysql: left join users on user.id=post.uid, how to do in 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
}
}
}
> secondary way,with ref attribute, but mgo.session will try to findid
for _,m := range posts{
db.FindRef(m.ref).One(&m.User)
}
> //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,你可以使用手动引用的方法来连接两个或多个相关的文档。例如,你的结构可以如下所示:
type User struct{
Id bson.ObjectId `bson:"_id"`
Name string `json:"name"`
}
type Post struct{
UserId bson.ObjectId `json:"userid"` // 对User的手动引用
Title string
}
然后,你可以使用$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)
示例结果:
{
"_id": ObjectId("590ab726f4bab950360c2dbe"),
"name": "test",
"posts": [
{
"_id": ObjectId("590ab72619663bad7743ff9e"),
"userid": ObjectId("590ab726f4bab950360c2dbe"),
"title": "test manual reference"
}
]
}
除了将用户和帖子存储在单独的集合中,你还可以选择嵌入/子文档的方式。详见数据建模。
英文:
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:
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
}
You can then use $lookup aggregation stage to perform a left outer join. For example, to find out all posts based on users:
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)
Example result:
{
"_id": ObjectId("590ab726f4bab950360c2dbe"),
"name": "test",
"posts": [
{
"_id": ObjectId("590ab72619663bad7743ff9e"),
"userid": ObjectId("590ab726f4bab950360c2dbe"),
"title": "test manual reference"
}
]
}
Alternative to storing users and posts in separate collections, you could also embed/sub-document. See also Data Modelling
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论