【问题标题】:MongoDB (mongoose) aggregate count instances of specific ObjectIDs in collectionMongoDB(猫鼬)聚合计数集合中特定 ObjectID 的实例
【发布时间】:2014-12-10 01:47:00
【问题描述】:

假设我有一个看起来像这样的架构:

{
    field: [{
        subDoc: ObjectId,
        ...
    }],
    ...
}

并且我有一些 ObjectIds(用户输入)列表,我将如何获得这些特定 ObjectIds 的计数?例如,如果我有这样的数据:

[
    {field: [ {subDoc: 123}, {subDoc: 234} ]},
    {field: [ {subDoc: 234}, {subDoc: 345} ]},
    {field: [ {subDoc: 123}, {subDoc: 345}, {subDoc: 456} ]}
]

用户给出的 id 列表是123, 234, 345,我需要对给定的 id 进行计数,所以结果近似于:

{
    123: 2,
    234: 2,
    345: 2
}

最好的方法是什么?

【问题讨论】:

    标签: javascript node.js mongodb mongoose aggregation-framework


    【解决方案1】:

    聚合框架本身如果不以您作为建议输出的方式动态命名键,那可能真的是一件好事。但你可能只需要这样查询:

    db.collection.aggregate([
        // Match documents that contain the elements
        { "$match": { 
            "field.subDoc": { "$in": [123,234,345] }
        }},
    
        // De-normalize the array field content
        { "$unwind": "$field" },
    
        // Match just the elements you want
        { "$match": { 
            "field.subDoc": { "$in": [123,234,345] }
        }},
    
        // Count by the element as a key
        { "$group": {
            "_id": "$field.subDoc",
            "count": { "$sum": 1 }
        }}
    ])
    

    这会给你这样的输出:

    { "_id" : 345, "count" : 2 }
    { "_id" : 234, "count" : 2 }
    { "_id" : 123, "count" : 2 }
    

    但是,如果您真的想对此发疯,您可以指定您想要的“键”作为查询的一部分,因此您可以形成这样的管道:

    db.collection.aggregate([
        { "$match": { 
            "field.subDoc": { "$in": [123,234,345] }
        }},
        { "$unwind": "$field" },
        { "$match": { 
            "field.subDoc": { "$in": [123,234,345] }
        }},
        { "$group": {
            "_id": "$field.subDoc",
            "count": { "$sum": 1 }
        }},
        { "$group": {
            "_id": null,
            "123": { 
                "$max": {
                    "$cond": [
                        { "$eq": [ "$_id", 123 ] },
                        "$count",
                        0
                    ]
                }
            },
            "234": { 
                "$max": {
                    "$cond": [
                        { "$eq": [ "$_id", 234 ] },
                        "$count",
                        0
                    ]
                }
            },
            "345": { 
                "$max": {
                    "$cond": [
                        { "$eq": [ "$_id", 345 ] },
                        "$count",
                        0
                    ]
                }
            }
        }}
    ])
    

    仅通过处理参数列表来构建代码的最后阶段是一件相对简单的事情:

    var list = [123,234,345];
    
    var group2 = { "$group": { "_id": null } };
    
    list.forEach(function(id) {
        group2["$group"][id] = { 
            "$max": {
                "$cond": [
                    { "$eq": [ "$_id", id ] },
                    "$count",
                    0
                ]
            }
        };
    });
    

    这或多或少是你想要的。

    { 
        "_id" : null, 
        "123" : 2, 
        "234" : 2, 
        "345" : 2 
    }
    

    【讨论】:

      【解决方案2】:

      不完全是你想要的,但它可以给你一个想法:

          db.test.aggregate([
          {
              $unwind: '$field'
          },
          {
              $group: {
                  _id: {
                      subDoc: '$field.subDoc'
                  },
                  count: {
                      $sum: 1
                  }
              }
          },
          {
              $project: {
                  subDoc: '$subDoc.subDoc',
                  count: '$count'
              }
          }
      ]);
      

      输出:

       {
          "result": [
              {
                  "_id": {
                      "subDoc": 456
                  },
                  "count": 1
              },
              {
                  "_id": {
                      "subDoc": 345
                  },
                  "count": 2
              },
              {
                  "_id": {
                      "subDoc": 234
                  },
                  "count": 2
              },
              {
                  "_id": {
                      "subDoc": 123
                  },
                  "count": 2
              }
          ],
          "ok": 1
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-24
        • 1970-01-01
        • 2016-02-02
        • 2013-11-23
        • 1970-01-01
        • 2015-05-19
        • 2021-08-05
        • 2013-01-12
        • 1970-01-01
        相关资源
        最近更新 更多