如何按子文档的字段总和进行排序

时间:2015-07-29 22:57:29

标签: mongodb meteor aggregation-framework

...并通过过滤器标准减少子文档?

我有以下数据结构

{
    "_id" : "PwS8gcfhaWLaudjaJ",
    "name" : "Name of Document 1",
    "subdocuments" : [ 
        {
            "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
            "number" : 1
        }, 
        {
            "subdocumentsId" : "vTaPoQYdaDbqMH7Pg",
            "number" : 1
        }, 
        {
            "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
            "number" : 3
        }
    ]
}
{
    "_id" : "PwS8gcfhaWLaudjaJ",
    "name" : "Name of Document 2",
    "subdocuments" : [ 
        {
            "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
            "number" : 2
        }, 
        {
            "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
            "number" : 5
        }
    ]
}

如何构建查询以获得以下结果

{
    "_id" : "PwS8gcfhaWLaudjaJ",
    "name" : "Name of Document 2",
    "subdocuments" : [ 
        {
            "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
            "number" : 2
        }, 
        {
            "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
            "number" : 5
        }
    ]
}
{
    "_id" : "PwS8gcfhaWLaudjaJ",
    "name" : "Name of Document 1",
    "subdocuments" : [ 
        {
            "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
            "number" : 1
        }, 
        {
            "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
            "number" : 3
        }
    ]
}

...这是我当前的查询

var filterIds = ['dqR9gPi7tNvzpEhEW','tPJ45KqAzvFPBRstZ'];

db.Documents
.aggregate([
{
    $match: {
        'subdocuments.subdocumentsId': {
            $in: filterIds
        }
    }
}, {
    $project: {
        _id: 1,
        name: 1,
        totalNumber: {
            $sum: '$subdocuments.number'
        }
    }
}, {
    $sort: {
        totalNumber: 1
    }
}
])

我无法在$ project-operation中使用$ sum-expression。它仅适用于$ group。

是否有共同的解决方法,或者是否可以使用$ group获得结果?

也许有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

使用数组时需要使用$unwind。此外,您还有两个$group操作,其间有$sort

db.Documents.aggregate([
    // Select documents
    { "$match": {
        "subdocuments.subdocumentsId": {
            "$in": filterIds
        }
    }}, 

    // Denormalize array
    { "$unwind": "subdocuments" }

    // Filter array elements
    { "$match": {
        "subdocuments.subdocumentsId": {
            "$in": filterIds
        }
    }}, 

    // Get array sum      
    { "$group": {
        "_id": {
            "_id": "$_id",
            "name": "$name",
            "subId": "$subdocuments.subdocumentsId"
        },
        "number": { "$sum": "$subdocuments.number" }
     }},

     // Sort the results
     { "$sort": { "_id._id": 1, "number": 1 } },

     // Group back to documents
     { "$group": {
         "_id": "$_id._id",
         "name": { "$first": "$_id.name" },
         "subdocuments": { "$push": {
             "subdocumentsId": "$_id.subId",
             "number": "$number"
         }},
         "total": { "$sum": "$number" }
     }},

     // Sort at the end, decending for largest first
     { "$sort": { "total": -1 } }
])

如果您通过其uinique“subdocumentId”值“汇总”过滤结果,那么这些值不是唯一的。如果您只是过滤,请减少步骤:

db.Documents.aggregate([
    // Select documents
    { "$match": {
        "subdocuments.subdocumentsId": {
            "$in": filterIds
        }
    }}, 

    // Denormalize array
    { "$unwind": "subdocuments" }

    // Filter array elements
    { "$match": {
        "subdocuments.subdocumentsId": {
            "$in": filterIds
        }
    }}, 

     // Group back to documents
     { "$group": {
         "_id": "$_id",
         "name": { "$first": "$name" },
         "subdocuments": {
            "$push": "$subdocuments"
         },
         "total": { "$sum": "$subdocuments.number" }
     }},

     // Sort at the end, decending for largest first
     { "$sort": { "total": -1 } }
])

答案 1 :(得分:1)

请尝试以下查询:

以下是获取结果所遵循的步骤:

1)展开您的子文档

2)仅保留与过滤器" filterIds匹配的文档 "标准

3)根据_id字段对文档进行分组,并保留" subdocuments.number"的总和。字段,以便我们可以根据它进行排序。

4)根据" subdocuments.number"进行排序。 field(tot)按降序排列。

5)最终以您需要的格式进行投影或显示。

db.Documents.aggregate([
{
 $unwind:"$subdocuments"
},
{
 $match:{"subdocuments.subdocumentsId" : {"$in" : filterIds }}
},
{
 $group:{ _id : { id : "$_id", name :"$name" },  
          tot : { "$sum": "$subdocuments.number"} , 
          subdocuments : {"$push" :
                         {subdocumentsId:"$subdocuments.subdocumentsId", 
          number : "$subdocuments.number" } }  } },
{
 $sort:{tot : -1}
},
{
 $project:{_id:"$_id.id", name: "$_id.name", subdocuments:1}
}
]).pretty();

因此上面的查询会获取所需的结果(OUTPUT):

{
        "_id" : "PwS8gcfhaWLaudjaI",
        "subdocuments" : [
                {
                        "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
                        "number" : 2
                },
                {
                        "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
                        "number" : 5
                }
        ],
        "name" : "Name of Document 2"
}
{
        "_id" : "PwS8gcfhaWLaudjaJ",
        "subdocuments" : [
                {
                        "subdocumentsId" : "dqR9gPi7tNvzpEhEW",
                        "number" : 1
                },
                {
                        "subdocumentsId" : "tPJ45KqAzvFPBRstZ",
                        "number" : 3
                }
        ],
        "name" : "Name of Document 1"
}
相关问题