在 Mongo Java 中分组后对多级数组进行排序
Sort multiple levels of array after group in Mongo Java
我有以下架构的文档
id :
currencyCode : "USD"
businessDayStartDate : ""
hourZoneNumber : 1
customerCount : 0
itemQuantity : 4
nodeId : "STORE_DEV"
endpointId : "998"
amount : 4
我正在尝试查找与 nodeId 匹配的文档,并尝试聚合每个 hourZoneNumber 的 customerCount、itemQuantity 和金额。
下面是查询
db.getCollection("xxx").aggregate([
{ "$match": { "nodeId": { "$in":["STORE_DEV_1","STORE_DEV_2"] }, "businessDayStartDate" : { "$gte": "2022-03-04" , "$lte": "2022-03-07" } }},
{ "$group": {
"_id": {
"nodeId": "$nodeId",
"endpointId": "$endpointId",
"hourZoneNumber": "$hourZoneNumber"
},
"customerCount": { "$sum": "$customerCount" },
"itemQuantity" : { "$sum": "$itemQuantity" },
"amount" : { "$sum": "$amount" }
}
},
{ "$group": {
"_id": {
"nodeId": "$_id.nodeId",
"endpointId": "$_id.endpointId"
},
"hourZones": {
"$addToSet": {
"hourZoneNumber": "$_id.hourZoneNumber",
"customerCount": { "$sum": "$customerCount" },
"itemQuantity" : { "$sum": "$itemQuantity" },
"amount" : { "$sum": "$amount" }
}
}
}
},
{ "$group": {
"_id": "$_id.nodeId",
"endpoints": {
"$addToSet": {
"endpointId": "$_id.endpointId",
"hourZones": "$hourZones"
}
},
"total": {
"$addToSet": {
"customerCount": { "$sum": "$hourZones.customerCount" },
"itemQuantity" : { "$sum": "$hourZones.itemQuantity" },
"amount" : { "$sum": "$hourZones.amount" }
}
}
}
},
{
$project: {
_id: 0,
nodeId: "$_id",
endpoints: 1,
hourZones: 1,
total: 1
}
}
])
输出如下:
{
nodeId: 'STORE_DEV_2',
endpoints: [
{ endpointId: '998',
hourZones:
[
{ hourZoneNumber: 1,
customerCount: 0,
itemQuantity: 4,
amount: Decimal128("4") }
] } ],
total: [ { customerCount: 0, itemQuantity: 4, amount: Decimal128("4") } ],
}
{
nodeId: 'STORE_DEV_1',
endpoints:
[ { endpointId: '999',
hourZones:
[ { hourZoneNumber: 2,
customerCount: 2,
itemQuantity: 4,
amount: Decimal128("4") },
{ hourZoneNumber: 1,
customerCount: 4,
itemQuantity: 8,
amount: Decimal128("247.56") } ] } ],
total:
[ { customerCount: 6,
itemQuantity: 12,
amount: Decimal128("251.56") } ]
}
我希望输出排序为:首先按 nodeId 排序,然后按端点内的 endpointId 排序,最后按 hourZones 内的 hourZoneNumber 排序。
我该怎么做?我尝试对所有三个字段使用 sort() 。但它没有用。另外,有人可以确认是否有比上述代码更好的方法,因为我是 Mongo 数据库的新手。
找到示例输入数据
因为一开始就已经有了分离的数据,所以只需要通过分组保存这些值,最后按它们排序即可。
编辑:为了对每个内部数组进行排序,我们在每个 $group
之前使用 $push
而不是 $group
和 $sort
中的 $addToSet
:
db.collection.aggregate([
{
"$match": {
"nodeId": {"$in": ["STORE_DEV_TTEC", "STORE_DEV_TTEZ"]
},
"businessDayStartDate": {"$gte": "2022-03-04", "$lte": "2022-03-07"}
}
},
{
"$sort": {"nodeId": 1, "endpointId": 1, "hourZoneNumber": 1}
},
{
"$group": {
"_id": {
"nodeId": "$nodeId",
"endpointId": "$endpointId",
"hourZoneNumber": "$hourZoneNumber"
},
"customerCount": {"$sum": "$customerCount"},
"itemQuantity": {"$sum": "$itemQuantity"},
"amount": {"$sum": "$amount"}
}
},
{"$sort": {"_id.hourZoneNumber": 1}
},
{
"$group": {
"_id": {
"nodeId": "$_id.nodeId",
"endpointId": "$_id.endpointId"
},
"hourZones": {
"$push": {
"hourZoneNumber": "$_id.hourZoneNumber",
"customerCount": {"$sum": "$customerCount"},
"itemQuantity": {"$sum": "$itemQuantity"},
"amount": {"$sum": "$amount"}
}
},
hourZoneKey: {$first: "$_id.hourZoneNumber"}
}
},
{"$sort": {"_id.endpointId": 1}
},
{
"$group": {
"_id": "$_id.nodeId",
"endpoints": {
"$push": {
"endpointId": "$_id.endpointId",
"hourZones": "$hourZones"
}
},
endpointKey: {$first: "$_id.endpointId"},
hourZoneKey: {$first: "$hourZoneKey"}
}
},
{"$sort": {"nodeId": 1, "endpointKey": 1, "hourZoneKey": 1}
},
{
$project: {_id: 0, nodeId: "$_id", endpoints: 1, hourZones: 1, total: 1}
}
])
可以看到here
我有以下架构的文档
id :
currencyCode : "USD"
businessDayStartDate : ""
hourZoneNumber : 1
customerCount : 0
itemQuantity : 4
nodeId : "STORE_DEV"
endpointId : "998"
amount : 4
我正在尝试查找与 nodeId 匹配的文档,并尝试聚合每个 hourZoneNumber 的 customerCount、itemQuantity 和金额。
下面是查询
db.getCollection("xxx").aggregate([
{ "$match": { "nodeId": { "$in":["STORE_DEV_1","STORE_DEV_2"] }, "businessDayStartDate" : { "$gte": "2022-03-04" , "$lte": "2022-03-07" } }},
{ "$group": {
"_id": {
"nodeId": "$nodeId",
"endpointId": "$endpointId",
"hourZoneNumber": "$hourZoneNumber"
},
"customerCount": { "$sum": "$customerCount" },
"itemQuantity" : { "$sum": "$itemQuantity" },
"amount" : { "$sum": "$amount" }
}
},
{ "$group": {
"_id": {
"nodeId": "$_id.nodeId",
"endpointId": "$_id.endpointId"
},
"hourZones": {
"$addToSet": {
"hourZoneNumber": "$_id.hourZoneNumber",
"customerCount": { "$sum": "$customerCount" },
"itemQuantity" : { "$sum": "$itemQuantity" },
"amount" : { "$sum": "$amount" }
}
}
}
},
{ "$group": {
"_id": "$_id.nodeId",
"endpoints": {
"$addToSet": {
"endpointId": "$_id.endpointId",
"hourZones": "$hourZones"
}
},
"total": {
"$addToSet": {
"customerCount": { "$sum": "$hourZones.customerCount" },
"itemQuantity" : { "$sum": "$hourZones.itemQuantity" },
"amount" : { "$sum": "$hourZones.amount" }
}
}
}
},
{
$project: {
_id: 0,
nodeId: "$_id",
endpoints: 1,
hourZones: 1,
total: 1
}
}
])
输出如下:
{
nodeId: 'STORE_DEV_2',
endpoints: [
{ endpointId: '998',
hourZones:
[
{ hourZoneNumber: 1,
customerCount: 0,
itemQuantity: 4,
amount: Decimal128("4") }
] } ],
total: [ { customerCount: 0, itemQuantity: 4, amount: Decimal128("4") } ],
}
{
nodeId: 'STORE_DEV_1',
endpoints:
[ { endpointId: '999',
hourZones:
[ { hourZoneNumber: 2,
customerCount: 2,
itemQuantity: 4,
amount: Decimal128("4") },
{ hourZoneNumber: 1,
customerCount: 4,
itemQuantity: 8,
amount: Decimal128("247.56") } ] } ],
total:
[ { customerCount: 6,
itemQuantity: 12,
amount: Decimal128("251.56") } ]
}
我希望输出排序为:首先按 nodeId 排序,然后按端点内的 endpointId 排序,最后按 hourZones 内的 hourZoneNumber 排序。
我该怎么做?我尝试对所有三个字段使用 sort() 。但它没有用。另外,有人可以确认是否有比上述代码更好的方法,因为我是 Mongo 数据库的新手。
找到示例输入数据因为一开始就已经有了分离的数据,所以只需要通过分组保存这些值,最后按它们排序即可。
编辑:为了对每个内部数组进行排序,我们在每个 $group
之前使用 $push
而不是 $group
和 $sort
中的 $addToSet
:
db.collection.aggregate([
{
"$match": {
"nodeId": {"$in": ["STORE_DEV_TTEC", "STORE_DEV_TTEZ"]
},
"businessDayStartDate": {"$gte": "2022-03-04", "$lte": "2022-03-07"}
}
},
{
"$sort": {"nodeId": 1, "endpointId": 1, "hourZoneNumber": 1}
},
{
"$group": {
"_id": {
"nodeId": "$nodeId",
"endpointId": "$endpointId",
"hourZoneNumber": "$hourZoneNumber"
},
"customerCount": {"$sum": "$customerCount"},
"itemQuantity": {"$sum": "$itemQuantity"},
"amount": {"$sum": "$amount"}
}
},
{"$sort": {"_id.hourZoneNumber": 1}
},
{
"$group": {
"_id": {
"nodeId": "$_id.nodeId",
"endpointId": "$_id.endpointId"
},
"hourZones": {
"$push": {
"hourZoneNumber": "$_id.hourZoneNumber",
"customerCount": {"$sum": "$customerCount"},
"itemQuantity": {"$sum": "$itemQuantity"},
"amount": {"$sum": "$amount"}
}
},
hourZoneKey: {$first: "$_id.hourZoneNumber"}
}
},
{"$sort": {"_id.endpointId": 1}
},
{
"$group": {
"_id": "$_id.nodeId",
"endpoints": {
"$push": {
"endpointId": "$_id.endpointId",
"hourZones": "$hourZones"
}
},
endpointKey: {$first: "$_id.endpointId"},
hourZoneKey: {$first: "$hourZoneKey"}
}
},
{"$sort": {"nodeId": 1, "endpointKey": 1, "hourZoneKey": 1}
},
{
$project: {_id: 0, nodeId: "$_id", endpoints: 1, hourZones: 1, total: 1}
}
])
可以看到here