2016-11-08 197 views
3

我試圖使用mgo包在go(golang)中的一個mongoDB查詢中實現$lookup功能。在Go(mgo.v2)中的MongoDB彙總查找

下面是我的收藏品:

文件夾:

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

下面是我寫的成功運行外殼上的查詢:

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並接收原始響應並自行解析它?

回答

4

找到解決方案!

訣竅是創建一個切片([]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。此外,我不得不改變了Documents領域的標籤我Folders結構的氧化鎂,以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 
} 

現在我只需要想出一個辦法,當我的Documents場不存儲在數據庫中保存一個Folder