简体   繁体   English

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

[英]MongoDB Aggregate lookup in Go (mgo.v2)

I'm trying to implement $lookup functionality in one of my mongoDB queries in go (golang) using the mgo package. 我试图实现$lookup使用中去(golang)在我的MongoDB查询的一个功能氧化镁包。

Below are my collections: 以下是我的收藏:

folders: 文件夹:

"_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")]

Below is the query I've written that successfully runs on the shell: 下面是我写的在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();

If I run this script on the shell, I get the desired result. 如果我在shell上运行此脚本,我会得到所需的结果。 Basically, the folder collection is returned to me containing the full relevant documents that were linked through the $lookup . 基本上, folder集合返回给我,其中包含通过$lookup链接的完整相关documents I'm not including it here because this question already seems too long. 我不在这里,因为这个问题似乎已经太久了。

I've tried to translate this query into something that mgo would be able to parse and execute. 我试图将此查询转换为mgo能够解析和执行的内容。 Here it is below in go code: 这里是下面的代码:

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)

I always get the same error: wrong type for field (pipeline) 3 != 4 我总是得到同样的错误: 字段(管道)3的错误类型!= 4

If I understand correctly, it's because it can't properly parse the result back into the $result object. 如果我理解正确,那是因为它无法正确地将结果解析回$ result对象。 I've done everything I can to ensure the struct has the exact structure that is required. 我已尽我所能确保结构具有所需的确切结构。 I've also tried to pass in a genereric []interface{} and an empty bson.M{} objects. 我也尝试传入一个genereric []interface{}和一个空的bson.M{}对象。 Still receive the same error. 仍然收到相同的错误。

Below is my Folders struct: 下面是我的文件夹结构:

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
}

I've also removed the $match clause to see if I could get anything at all back from that $lookup query. 我还删除了$match子句,看看我是否可以从$lookup查询得到任何结果。 But I still get the same error. 但我仍然得到同样的错误。

Perhaps the mgo package doesn't support $lookup ? 也许mgo包不支持$lookup If so, would there be another way? 如果是这样,会有另一种方式吗? Perhaps I could send the raw query text to mongo and receive the raw response and parse it myself? 也许我可以将原始查询文本发送到mongo并接收原始响应并自己解析它?

Found the solution! 找到了解决方案!

The trick was to create the query in a slice ( []bson.M ) and change the structure of the query a bit: 诀窍是在切片( []bson.M )中创建查询并[]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)

I found a clue in mgo's Pipe function docs . 我在mgo的Pipe函数文档中找到了一个线索。 Also, I had to change the tags for the Documents field in my Folders struct for mgo to pupolate that field: 另外,我必须更改我的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
}

Now I just have to figure out a way to not store the Documents field in the database when I save a Folder . 现在,我只需要找出一种在保存Folder时不将Documents字段存储在数据库中的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM