(mongo)我怎样才能获得数组中包含值的文档以及大小

时间:2017-11-11 18:36:07

标签: mongodb

我有一个类似下面的mongo集合:

 { 
    "_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"
    }
}

现在我怎样才能获得与名称类别1竞争的文件数量超过一次或超过2次......依此类推

我尝试使用尺寸和$ gt但无法形成正确的结果

3 个答案:

答案 0 :(得分:2)

假设单个contest永远不会包含相同的name(例如" Category1")值,您可以执行以下操作。

缺少任何unwind将导致性能提升,特别是对于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
})

答案 1 :(得分: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} }}

  ]);

答案 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}}]}}]);