如何按子文档的字段总和排序
How to sort by a field-sum of a subdocument
...并按过滤条件减少子文档?
我有以下数据结构
{
"_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 获得结果?
也许有人可以帮忙?
你需要在两者之间使用$unwind
when working with arrays. Also you have two $group
operations here with a $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 } }
])
也就是说,如果您 "summing" 通过其唯一 "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) 展开您的子文档
2) 只保留那些匹配过滤器“filterIds”的文档
" 标准
3) 根据 _id 字段对文档进行分组,并保留 "subdocuments.number" 字段的总和,以便我们可以根据它进行排序。
4) 根据 "subdocuments.number" 字段 (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();
所以上面的查询获取了你想要的结果(输出):
{
"_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"
}
...并按过滤条件减少子文档?
我有以下数据结构
{
"_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 获得结果?
也许有人可以帮忙?
你需要在两者之间使用$unwind
when working with arrays. Also you have two $group
operations here with a $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 } }
])
也就是说,如果您 "summing" 通过其唯一 "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) 展开您的子文档
2) 只保留那些匹配过滤器“filterIds”的文档 " 标准
3) 根据 _id 字段对文档进行分组,并保留 "subdocuments.number" 字段的总和,以便我们可以根据它进行排序。
4) 根据 "subdocuments.number" 字段 (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();
所以上面的查询获取了你想要的结果(输出):
{
"_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"
}