MongoDB Go 中的聚合查找 (mgo.v2)
MongoDB Aggregate lookup in Go (mgo.v2)
我正在尝试使用 mgo 包在我的 mongoDB 查询之一中实现 $lookup
功能。
下面是我的 collections:
文件夹:
"_id" : ObjectId("22222222222222"),
"name" : "Media",
"level" : 1,
"userIDs": [ObjectId("4444444444444")]
文件:
"_id" : ObjectId("11111111111111"),
"title" : "Media Management",
"body" : BinData(0,"PvQ6z2NBm4265duo/e2XsYxA5bXKo="),
"level" : 1,
"folderID" : ObjectId("22222222222222"), // Foreign Key/Field
"userIDs" : [ObjectId("44444444444444")]
下面是我在 shell 上成功编写的查询 运行:
var query = [
{
"$lookup": {
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
}
}
,{
"$match": {
"userIDs": ObjectId("userIdHere"), // filder by a userID
"level": {$gte: 0}, // filter by a folder level
},
}
];
db.folders.aggregate(query).pretty().shellPrint();
如果我 运行 这个脚本放在 shell 上,我会得到想要的结果。基本上,返回给我的 folder
collection 包含通过 $lookup
链接的完整相关 documents
。我没有把它包括在这里,因为这个问题似乎已经太长了。
我已尝试将此查询翻译成 mgo 能够解析和执行的内容。这是下面的代码:
query := bson.M{
"$lookup": bson.M{ // lookup the documents table here
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
},
"$match": bson.M{
"level": bson.M{"$gte": user.Level}, // filter by level
"userIDs": user.ID, // filter by user
},
}
pipe := collection.Pipe(query) // querying the "folders" collection
err := pipe.All(&result)
我总是得到同样的错误:错误的字段类型(管道)3 != 4
如果我没理解错的话,那是因为它不能正确地将结果解析回 $result object。我已尽我所能确保该结构具有所需的确切结构。我还尝试传递一个通用的 []interface{}
和一个空的 bson.M{}
objects。仍然收到相同的错误。
下面是我的文件夹结构:
type Folder struct {
ID bson.ObjectId `json:"id" bson:"_id"`
Name string `json:"name"`
Level int `json:"level"`
UserIDs []bson.ObjectId `json:"userIDs" bson:"userIDs"`
Users []User `json:"-" bson:"-"` // doesn't get stored in the database
Documents []Document `json:"-" bson:"-"` // doesn't get stored in the database
}
我还删除了 $match
子句,看看是否可以从 $lookup
查询中得到任何结果。但是我仍然得到同样的错误。
也许mgo 包不支持$lookup
?如果是这样,是否还有另一种方法? 也许我可以将原始查询文本发送到 mongo 并接收原始响应并自己解析?
找到解决方案!
诀窍是在切片中创建查询 ([]bson.M
) 并稍微更改查询的结构:
query := []bson.M{{
"$lookup": bson.M{ // lookup the documents table here
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
}},
{"$match": bson.M{
"level": bson.M{"$lte": user.Level},
"userIDs": user.ID,
}}}
pipe := collection.Pipe(query)
err := pipe.All(&folders)
我在 mgo's Pipe function docs 中找到了线索。此外,我必须更改 Folders
结构中 Documents
字段的标签,以便 mgo 对该字段进行 pupolate:
type Folder struct {
ID bson.ObjectId `json:"id" bson:"_id"`
Name string `json:"name"`
Level int `json:"level"`
UserIDs []bson.ObjectId `json:"userIDs" bson:"userIDs"`
Users []User `json:"-" bson:"-"` // doesn't get stored in the database
Documents []Document // `json:"-" bson:"-" Removed this so that mgo can unmarshal
// the documents correctly
}
现在我只需要想办法在保存 Folder
时不在数据库中存储 Documents
字段。
我正在尝试使用 mgo 包在我的 mongoDB 查询之一中实现 $lookup
功能。
下面是我的 collections:
文件夹:
"_id" : ObjectId("22222222222222"),
"name" : "Media",
"level" : 1,
"userIDs": [ObjectId("4444444444444")]
文件:
"_id" : ObjectId("11111111111111"),
"title" : "Media Management",
"body" : BinData(0,"PvQ6z2NBm4265duo/e2XsYxA5bXKo="),
"level" : 1,
"folderID" : ObjectId("22222222222222"), // Foreign Key/Field
"userIDs" : [ObjectId("44444444444444")]
下面是我在 shell 上成功编写的查询 运行:
var query = [
{
"$lookup": {
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
}
}
,{
"$match": {
"userIDs": ObjectId("userIdHere"), // filder by a userID
"level": {$gte: 0}, // filter by a folder level
},
}
];
db.folders.aggregate(query).pretty().shellPrint();
如果我 运行 这个脚本放在 shell 上,我会得到想要的结果。基本上,返回给我的 folder
collection 包含通过 $lookup
链接的完整相关 documents
。我没有把它包括在这里,因为这个问题似乎已经太长了。
我已尝试将此查询翻译成 mgo 能够解析和执行的内容。这是下面的代码:
query := bson.M{
"$lookup": bson.M{ // lookup the documents table here
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
},
"$match": bson.M{
"level": bson.M{"$gte": user.Level}, // filter by level
"userIDs": user.ID, // filter by user
},
}
pipe := collection.Pipe(query) // querying the "folders" collection
err := pipe.All(&result)
我总是得到同样的错误:错误的字段类型(管道)3 != 4
如果我没理解错的话,那是因为它不能正确地将结果解析回 $result object。我已尽我所能确保该结构具有所需的确切结构。我还尝试传递一个通用的 []interface{}
和一个空的 bson.M{}
objects。仍然收到相同的错误。
下面是我的文件夹结构:
type Folder struct {
ID bson.ObjectId `json:"id" bson:"_id"`
Name string `json:"name"`
Level int `json:"level"`
UserIDs []bson.ObjectId `json:"userIDs" bson:"userIDs"`
Users []User `json:"-" bson:"-"` // doesn't get stored in the database
Documents []Document `json:"-" bson:"-"` // doesn't get stored in the database
}
我还删除了 $match
子句,看看是否可以从 $lookup
查询中得到任何结果。但是我仍然得到同样的错误。
也许mgo 包不支持$lookup
?如果是这样,是否还有另一种方法? 也许我可以将原始查询文本发送到 mongo 并接收原始响应并自己解析?
找到解决方案!
诀窍是在切片中创建查询 ([]bson.M
) 并稍微更改查询的结构:
query := []bson.M{{
"$lookup": bson.M{ // lookup the documents table here
"from": "documents",
"localField": "_id",
"foreignField": "folderID",
"as": "documents",
}},
{"$match": bson.M{
"level": bson.M{"$lte": user.Level},
"userIDs": user.ID,
}}}
pipe := collection.Pipe(query)
err := pipe.All(&folders)
我在 mgo's Pipe function docs 中找到了线索。此外,我必须更改 Folders
结构中 Documents
字段的标签,以便 mgo 对该字段进行 pupolate:
type Folder struct {
ID bson.ObjectId `json:"id" bson:"_id"`
Name string `json:"name"`
Level int `json:"level"`
UserIDs []bson.ObjectId `json:"userIDs" bson:"userIDs"`
Users []User `json:"-" bson:"-"` // doesn't get stored in the database
Documents []Document // `json:"-" bson:"-" Removed this so that mgo can unmarshal
// the documents correctly
}
现在我只需要想办法在保存 Folder
时不在数据库中存储 Documents
字段。