2015-06-16 56 views
2

我想寫一個聚合查詢使用$展開無論該元素是否是一個數組或不。我知道$unwind不能在沒有數組元素的情況下工作,但我想知道是否有辦法使它工作,就像將此元素轉換爲數組一樣。mongodb聚合展開陣列和沒有數組

我有這樣一個集合:

{ 

    {"x" : 1, "y" : {"c" : 2, "i" : 3}}, 
    {"x" : 1, "y" : [{"c" : 4, "i" : 5}, {"c" : 6, "i" : 7}]} 

} 

之前我$unwind我想我需要這樣的:

{ 

    {"x" : 1, "y" : [{"c" : 2, "i" : 3}]}, 
    {"x" : 1, "y" : [{"c" : 4, "i" : 5}, {"c" : 6, "i" : 7}]} 
} 

至今$project階段,我可以檢查是否元素數組或不,但我不知道如何使用這些信息來創建數組。我知道我可以使用$push來創建一個數組,但是如何留下未觸動過的數組元素而只是$push沒有數組元素?

我嘗試這樣做:

{$group : {"_id" : "$x", "myArray" : {$push : {$cond : {if : "$isArray", then : "$y", else : ["$y"]}}}}} 

有了上面的代碼,我試圖在同一級別的所有元素,但因爲["$y"]回報正是(["$y"])沒有工作,沒有任何評價,只是一個字符串數組它。

我不想$展開一個空數組,我想將一個非數組元素轉換爲一個數組元素,所以我可以$放鬆。

任何幫助將不勝感激。

+0

我不明白你關於把樣品改成同樣的東西的評論。第一個示例包含「y」的數組和非數組元素,第二個示例是我所定義的元素,所有「y」元素都是數組。 關於可能的重複,我認爲這不是我的情況,因爲我沒有和空陣列。我有一個非數組元素,我想變成數組,所以我可以放鬆。 –

+0

我同意這不是一個好主意,但我沒有寫這個集合,現在也不能改變它。 –

回答

4

這基本上是你想要從$cond$ifNull一些幫助什麼:

db.collection.aggregate([ 
    { "$project": { 
     "x": 1, 
     "y": { 
      "$cond": [ 
       { "$ifNull": [ "$y.0", null] }, 
       "$y", 
       { "$map": { 
        "input": ["A"], 
        "as": "el", 
        "in": "$y" 
       }} 
      ] 
     } 
    }} 
]) 

因此,那些第一條件制定出「是元素的數組」通過的「先存在基本測試索引「的數組元素。如果條件爲真,則使用現有元素,即數組。

如果不是這樣,元素通過$map函數和單個「虛擬」數組元素「轉換」爲數組。

輸出就是你想要什麼:

{ 
    "_id" : ObjectId("557f9d9d655c7c61fdcb7909"), 
    "x" : 1, 
    "y" : [ 
      { 
        "c" : 2, 
        "i" : 3 
      } 
    ] 
} 
{ 
    "_id" : ObjectId("557f9d9d655c7c61fdcb790a"), 
    "x" : 1, 
    "y" : [ 
      { 
        "c" : 4, 
        "i" : 5 
      }, 
      { 
        "c" : 6, 
        "i" : 7 
      } 
    ] 
} 

我還是會建議如果可能的話,你改變文件實際上包含您的收藏在一個數組元素,而不是工作到這個管道。像這樣的事情:

db.collection.find({ "y.0": { "$exists": false } }).forEach(function(doc) { 
    db.collection.update(
     { "_id": doc._id }, 
     { "$set": { "y": [doc.y] } } 
    ) 
}) 
+0

這很好,我仍然需要了解它,但它很好用。非常感謝。我不能投票,但如果我能的話,我會。 –

+0

@RaulMartinez您可能還沒有獲得「upvote」答案所需的特權,但您可以[接受](http:// stackoverflow。com/help/accepted-answer)一個 –