使用Go语言(mgo.v2)实现MongoDB聚合查询的lookup操作

4
我想在使用mgo包的go(golang)中实现$lookup功能来查询我的mongoDB。以下是我的集合:

文件夹:

"_id"    : ObjectId("22222222222222"),
"name"   : "Media",
"level"  : 1,
"userIDs": [ObjectId("4444444444444")]

documents:

"_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集合会被返回给我,其中包含通过$lookup链接的所有相关documents。我没有在此处包含它,因为这个问题似乎已经太长了。
我尝试将这个查询转换为mgo能够解析和执行的内容。以下是go代码:
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)

我总是遇到同样的错误:字段类型错误 (pipeline) 3 != 4

如果我理解正确,这是因为它无法将结果正确解析回 $result 对象。我已经尽我所能确保结构具有所需的精确结构。我还尝试传递一个通用的 []interface{} 和一个空的 bson.M{} 对象。仍然收到相同的错误。

以下是我的文件夹结构:

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,然后接收原始响应并自行解析?
1个回答

8

找到解决方案了!

窍门是在一个片段中 ([]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的Pipe函数文档中找到了线索。此外,我不得不更改我的Folders结构中的Documents字段的标签,以便mgo可以填充该字段:

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
}

现在我只需要想办法在保存文件夹时不将文档字段存储到数据库中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接