Go 中的 MongoDB 聚合查找 (mgo.v2)

标签 mongodb go mongodb-query aggregation-framework mgo

我正在尝试使用 mgo 在 go (golang) 中的一个 mongoDB 查询中实现 $lookup 功能包。

以下是我的收藏:

文件夹:

"_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 集合包含通过 $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)

我总是遇到同样的错误:字段(管道)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 并接收原始响应并自行解析?

最佳答案

找到解决方案!

诀窍是在 slice ([]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 字段。

关于Go 中的 MongoDB 聚合查找 (mgo.v2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40484271/

相关文章:

javascript - 简单MongoDB查询查找项目年龄>10 learnyoumongo查找函数

go - 为具有多个主机 ip 的 cassandra 迁移库实现

docker 检查 : how to select only certain keys from range

javascript - Mongoose 查询查找,结果是我找到结果的字段名称

node.js - 将 ObjectId 转换为 MongoDB 中的字符串

MongoDB 查找和迭代 vs 计数

mongodb - "fastmod"在mongodb日志中意味着什么

mongodb - 如果未找到结果,则返回 null 默认值

node.js - PhoneJS w Ripple模拟器无法连接到本地 Node 服务器

go - json 编码结构数组的一个属性