1

我有一個數據集,看起來是這樣的:麻煩MongoDB中創建的查詢與子查詢

{ 
 
    "id": "02741544", 
 
    "items": [{ 
 
    "item": "A" 
 
    }] 
 
}, { 
 
    "id": "02472691", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }, { 
 
    "item": "C" 
 
    }] 
 
}, { 
 

 
    "id": "01316523", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }] 
 
}, { 
 
    "id": "01316526", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "B" 
 
    }] 
 
}, { 
 
    "id": "01316529", 
 
    "items": [{ 
 
    "item": "A" 
 
    }, { 
 
    "item": "D" 
 
    }] 
 
},

我想製作一個查詢,這將使我的輸出,看起來像這樣的:

{ 
 
    "item": "A", 
 
    "ids": [{ 
 
    "id": "02741544" 
 

 
    }, { 
 
    "id": "02472691" 
 

 
    }, { 
 
    "id": "01316523" 
 

 
    }, { 
 
    "id": "01316526" 
 

 
    }, { 
 
    "id": "01316529" 
 

 
    }] 
 
}, { 
 
    "item": "B", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }, { 
 
    "id": "01316523" 
 

 
    }, { 
 
    "id": "01316526" 
 

 
    }] 
 
}, { 
 
    "item": "C", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }] 
 
}, { 
 
    "item": "D", 
 
    "ids": [{ 
 
    "id": "02472691" 
 

 
    }] 
 
},

基本上,我試圖從對象中的項目數組中獲取不同的項目,然後爲每個在其項目數組中具有該項目的obj返回一個id數組。

回答

2

更好地利用aggregation framework中,你需要運行一個由以下管道的步驟(給定的順序)操作:

  1. $unwind - 這第一步將壓平items陣列即它爲每個數組條目生成每個文檔的副本。這對於將流水線下方的文檔處理爲「非規範化」文檔是必要的,您可以將這些文檔聚合爲組。
  2. $group - 這組扁平文件由item子文檔密鑰,使用該$push蓄電池運營商創建ids列表。

- 更新 -

由於@AminJ在評論中指出,如果items可以有重複的項目值,你不想在結果中重複的ID,你可以使用$addToSet代替$push

下面的例子說明這一點:

db.collection.aggregate([ 
    { "$unwind": "$items" }, 
    { 
     "$group": { 
      "_id": "$items.item", 
      "ids": { 
       "$push": { "id": "$id" } /* or use 
       "$addToSet": { "id": "$id" } if you don't want duplicate ids */      
      } 
     } 
    } 
]) 

樣本輸出

{ 
    "_id" : "A", 
    "ids" : [ 
     { "id" : "02741544" }, 
     { "id" : "02472691" }, 
     { "id" : "01316523" }, 
     { "id" : "01316526" }, 
     { "id" : "01316529" } 
    ] 
} 

/* 2 */ 
{ 
    "_id" : "B", 
    "ids" : [ 
     { "id" : "02472691" }, 
     { "id" : "01316523" }, 
     { "id" : "01316526" } 
    ] 
} 

/* 3 */ 
{ 
    "_id" : "C", 
    "ids" : [ 
     { "id" : "02472691" } 
    ] 
} 

/* 4 */ 
{ 
    "_id" : "D", 
    "ids" : [ 
     { "id" : "01316529" } 
    ] 
} 

aggregate()功能的結果是一個光標移動到由聚合流水線操作的最後階段中產生的文檔。所以如果你想在一個數組中得到結果,你可以使用光標的方法,該方法返回一個數組,該數組包含來自它的所有文檔。

例如:

var pipeline = [  
     { "$unwind": "$items" }, 
     { 
      "$group": { 
       "_id": "$items.item", 
       "ids": { 
        "$push": { "id": "$id" } /* or use 
        "$addToSet": { "id": "$id" } if you don't want duplicate ids */      
       } 
      } 
     } 
    ], 
    results = db.collection.aggregate(pipeline).toArray(); 

printjson(results); 
+1

這可能是值得一提,如果'items'可以有重複的'item'值,並且你不想在結果中可以使用'addToSet'而不是'push'。 –

+0

@AminJ好點 – chridam

+0

只要內容進行,它就會給出所需的輸出,但不會將結果作爲一組對象返回。這是如何完成的? – TWLATL

0

下面是一個使用聚合管道解決方案:

db.col.aggregate([ 
     { 
      $unwind: "$items" 
     }, 
     { 
      $project: { 
       id: 1, 
       item: "$items.item" 
      } 
     }, 
     { 
      $group: { 
       _id: "$item", 
       ids: { 
        $push: "$id" 
       } 
      } 
     } 
    ])