2017-11-11 73 views
0

沿着在陣列中的有價票券我有一個蒙戈收藏的東西,如以下:(蒙戈)我怎麼能得到與大小

{ 
    "_id" : ObjectId("59e013e83260c739f029ee21"), 
    "createdAt" : ISODate("2017-10-13T01:16:24.653+0000"), 
    "updatedAt" : ISODate("2017-11-11T17:13:52.956+0000"), 
    "age" : NumberInt(34), 
    "attributes" : [ 
     { 
      "year" : "2017", 
      "contest" : [ 
       { 
        "name" : "Category1", 
        "division" : "Department1" 
       }, 
       { 
        "name" : "Category2", 
        "division" : "Department1" 
       } 
      ] 
     }, 
     { 
      "year" : "2016", 
      "contest" : [ 
       { 
        "name" : "Category2", 
        "division" : "Department1" 
       } 
      ] 
     }, 
     { 
      "year" : "2015", 
      "contest" : [ 
       { 
        "name" : "Category1", 
        "division" : "Department1" 
       } 
      ] 
     } 
    ], 
    "name" : { 
     "id" : NumberInt(9850214), 
     "first" : "john", 
     "last" : "afham" 
    } 
} 

現在我怎麼能拿誰擁有的文件數量競賽名稱爲組別超過一次或2次以上......等等

我試圖用規模和$ GT,但不能形成正確的結果

+0

粘貼集合中的示例數據。這個數據看起來不對 – Astro

+0

看起來像上面的數據是不正確的 – Sam

+0

@astro我已經更新json數據,這是100%喜歡從集合中提取 –

回答

2

假設一個contest絕不會含有相同的name(例如「組別」)值超過一次,這裏是你可以做什麼。

沒有任何unwind S的將導致特別改進的性能上大集或數據集與您attributes陣列條目的負荷。

db.collection.aggregate({ 
    $project: { 
     "numberOfOccurrences": { 
      $size: { // count the number of matching contest elements 
       $filter: { // get rid of all contest entries that do not contain at least one entry with name "Category1" 
        input: "$attributes", 
        cond: { $in: [ "Category1", "$$this.contest.name" ] } 
       } 
      } 
     } 
    } 
}, { 
    $match: { // filter the number of documents 
     "numberOfOccurrences": { 
      $gt: 1 // put your desired min. number of matching contest entries here 
     } 
    } 
}, { 
    $count: "numberOfDocuments" // count the number of matching documents 
}) 
+0

這裏使用了數組點運算(this.contest.name)! –

0

試試這個關於大小。

db.foo.aggregate([ 
    // Start with breaking down attributes: 
    {$unwind: "$attributes"} 

    // Next, extract only name = Category1 from the contest array. This will yield     
    // an array of 0 or 1 because I am assuming that contest names WITHIN 
    // the contest array are unique. If found and we get an array of 1, turn that     
    // into a single doc instead of an array of a single doc by taking arrayElemAt 0.     
    // Otherwise, "x" is not set into the doc AT ALL. All other vars in the doc 
    // will go away after $project; if you want to keep them, change this to 
    // $addFields: 
    ,{$project: {x: {$arrayElemAt: [ {$filter: { 
      input: "$attributes.contest", 
      as: "z", 
      cond: {$eq: [ "$$z.name", "Category1" ]} 
       }}, 0 ]} 
    }} 

    // We split up attributes before, creating multiple docs with the same _id. We     
    // must now "recombine" these _id (OP said he wants # of docs with name). 
    // We now have to capture all the single "x" that we created above; docs without     
    // Category1 will have NO "x" and we don't want to include them in the count.      
    // Also, we KNOW that name can only be Category 1 but division could vary, so      
    // let's capture that in the $push in case we might want it: 
    ,{$group: {_id: "$_id", x: {$push: "$x.division"}}} 

    // One more pass to compute length of array: 
    ,{$addFields: {len: {$size: "$x"}} } 

    // And lastly, the filter for one time or two times or n times: 
    ,{$match: {len: {$gt: 2} }} 

    ]); 
0

首先,我們需要通過屬性和競賽字段來平整文檔。然後由文件初始_id和比賽名稱統計不同的比賽。最後,我們過濾結果。

db.person.aggregate([ 
    { $unwind: "$attributes" }, 
    { $unwind: "$attributes.contest" }, 

    {$group: { 
       _id: {initial_id: "$_id", contest: "$attributes.contest.name"}, 
       count: {$sum: 1} 
      } 
    }, 
    {$match: {$and: [{"_id.contest": "Category1"}, {"count": {$gt: 1}}]}}]); 
+0

Double $ unwind在更大的陣列情況下可能是致命的。 drickless發佈了上面的$ unwind-free示例。 –

+0

@ BuzzMoschetti也許它可以,drickless已經對數據做了一些假設,而我沒有。無論如何,這是很好的選擇可供選擇。 –