英文:
mongo db. Group documents in array, score them count and sum and add new field
问题
我可以为您翻译代码的这部分内容。以下是代码的翻译部分:
我有两个集合:
> 包含一些操作的集合:
[
{
"id": 0,
"action": "qwe",
"timestamp": "2022-11-20T23:59:59",
"user": "test"
},
{
"id": 1,
"action": "zwe",
"timestamp": "2022-11-20T11:22:33",
"user": "test"
},
{
"id": 1,
"action": "qwe",
"timestamp": "2022-11-20T11:22:33",
"user": "test"
}
]
> 以及包含这些操作分数的集合:
[
{
"action": "qwe",
"score": 5
},
{
"action": "zwe",
"score": 3
},
{
"action": "qwe",
"score": 5
}
]
> 我需要实现以下结果:
[
{
"user": "test",
"actions": [
{
"action": "qwe",
"score": 5,
"timestamp": "2022-11-17T12:55:34.804+00:00"
},
{
"action": "zwe",
"score": 3,
"timestamp": "2022-11-17T12:55:34.804+00:00"
},
{
"action": "qwe",
"score": 5,
"timestamp": "2022-11-18T12:51:11.804+00:00"
}
],
"actions_total": [
{
"action": "qwe",
"count": 2,
"total_score": 10
},
{
"action": "zwe",
"count": 1,
"total_score": 3
}
],
"total_score": 13
}
]
> 我编写了以下聚合操作:
[
{
$match: {
timestamp: {
$gte: ISODate('2022-11-17T00:00:00'),
$lte: ISODate('2022-11-20T23:59:59')
}
}
},
{
$lookup: {
from: 'actions_score',
localField: 'action',
foreignField: 'action',
as: 'score'
}
},
{
$unwind: {
path: "$score"
}
},
{
$project: {
'username': true,
'action': true,
'score': '$score.score',
'timestamp': true,
'role_id': true,
'_id': false
}
},
{
$group: {
_id: '$username',
'username': {
$first: '$username'
},
'role_id': {
$first: '$role_id'
},
'actions': {
$addToSet: '$$ROOT'
}
}
},
{
$addFields: {
'total_score': {
"$sum": "$actions.score"
}
}
},
{
$project: {
_id: false,
'actions.username': false,
'actions.role_id': false
}
}
]
> 然后我得到了以下结果:
[
{
"user": "test",
"actions": [
{
"action": "qwe",
"score": 5,
"timestamp": "2022-11-17T12:55:34.804+00:00"
},
{
"action": "zwe",
"score": 3,
"timestamp": "2022-11-17T12:55:34.804+00:00"
},
{
"action": "qwe",
"score": 5,
"timestamp": "2022-11-18T12:51:11.804+00:00"
}
],
"total_score": 13
}
]
> 问题:
我如何可以获得这一部分?我如何可以按操作字段对文档进行分组并获得期望的结果?
"actions_total": [
{
"action": "qwe",
"count": 2,
"total_score": 10
},
{
"action": "zwe",
"count": 1,
"total_score": 3
}
]
将不胜感激您的帮助!
英文:
I have two collections:
> Collections with some actions:
[
{
"id": 0,
"action": "qwe",
"timestamp": "2022-11-20T23:59:59",
"user": "test"
},
{
"id": 1,
"action": "zwe",
"timestamp": "2022-11-20T11:22:33",
"user": "test"
},
{
"id": 1,
"action": "qwe",
"timestamp": "2022-11-20T11:22:33",
"user": "test"
}
]
> And collection with score of this actions:
[
{
"action": "qwe",
"score": 5
},
{
"action": "zwe",
"score": 3
},
{
"action": "qwe",
"score": 5
}
]
> I need achieve next results:
[
{
"user": "test",
"actions": [
{
"action":"qwe",
"score":5,
"timestamp":"2022-11-17T12:55:34.804+00:00"
},
{
"action":"zwe",
"score":3,
"timestamp":"2022-11-17T12:55:34.804+00:00"
},
{
"action":"qwe",
"score":5,
"timestamp":"2022-11-18T12:51:11.804+00:00"
}
],
"actions_total": [
{
"action": "qwe",
"count": 2,
"total_score": 10
},
{
"action": "zwe",
"count": 1,
"total_score": 3
}
],
"total_score": 13
}
]
> I write next aggregation:
[
{
$match: {
timestamp: {
$gte: ISODate(
'2022-11-17T00:00:00'
),
$lte: ISODate(
'2022-11-20T23:59:59'
)
}
}
},
{
$lookup: {
from: 'actions_score',
localField: 'action',
foreignField: 'action',
as: 'score'
}
},
{
$unwind: {
path: "$score"
}
},
{
$project: {
'username': true,
'action': true,
'score': '$score.score',
'timestamp': true,
'role_id': true,
'_id': false
}
},
{
$group: {
_id: '$username',
'username': {
$first: '$username'
},
'role_id': {
$first: '$role_id'
},
'actions': {
$addToSet: '$$ROOT'
}
}
},
{
$addFields: {
'total_score': {
"$sum": "$actions.score"
}
}
},
{
$project: {
_id: false,
'actions.username': false,
'actions.role_id': false
}
}
]
> And i get next result:
[
{
"user": "test",
"actions": [
{
"action":"qwe",
"score":5,
"timestamp":"2022-11-17T12:55:34.804+00:00"
},
{
"action":"zwe",
"score":3,
"timestamp":"2022-11-17T12:55:34.804+00:00"
},
{
"action":"qwe",
"score":5,
"timestamp":"2022-11-18T12:51:11.804+00:00"
}
],
"total_score": 13
}
]
> Question:
How i can get this part? How i can grop documents by field actions and get expected results?
"actions_total": [
{
"action": "qwe",
"count": 2,
"total_score": 10
},
{
"action": "zwe",
"count": 1,
"total_score": 3
}
]
Will be grateful for the help!
答案1
得分: 1
以下是翻译好的部分代码:
One option is to use `$group` twice and then `$reduce` to flatten the array:
db.actions.aggregate([
{$match: {timestamp: {
$gte: ISODate("2022-11-17T00:00:00Z"),
$lte: ISODate("2022-11-20T23:59:59Z")
}},
{$lookup: {
from: "actions_score",
localField: "action",
foreignField: "action",
as: "score"
}},
{$project: {
user: 1, _id: 0, action: 1, score: {$first: "$score.score"}, timestamp: 1}},
{$group: {
_id: {user: "$user", action: "$action"},
count: {$sum: 1},
total_score: {$sum: "$score"},
actions: {$addToSet: "$$ROOT"}
}},
{$group: {
_id: "$_id.user",
user: {$first: "$_id.user"},
actions: {$push: "$actions"},
actions_total: {$push: {
action: "$_id.action",
count: "$count",
total_score: "$total_score"
}},
total_score: {$sum: "$total_score"}
}},
{$set: {
actions: {$reduce: {
input: "$actions",
initialValue: [],
in: {$concatArrays: "$$value", "$$this"}
}}
}}
])
您可以在playground示例上查看它的运行方式。
英文:
One option is to use $group
twice and then $reduce
to flatten the array:
db.actions.aggregate([
{$match: {timestamp: {
$gte: ISODate("2022-11-17T00:00:00Z"),
$lte: ISODate("2022-11-20T23:59:59Z")
}}},
{$lookup: {
from: "actions_score",
localField: "action",
foreignField: "action",
as: "score"
}},
{$project: {
user: 1, _id: 0, action: 1, score: {$first: "$score.score"}, timestamp: 1}},
{$group: {
_id: {user: "$user", action: "$action"},
count: {$sum: 1},
total_score: {$sum: "$score"},
actions: {$addToSet: "$$ROOT"}
}},
{$group: {
_id: "$_id.user",
user: {$first: "$_id.user"},
actions: {$push: "$actions"},
actions_total: {$push: {
action: "$_id.action",
count: "$count",
total_score: "$total_score"
}},
total_score: {$sum: "$total_score"}
}},
{$set: {
actions: {$reduce: {
input: "$actions",
initialValue: [],
in: {$concatArrays: ["$$value", "$$this"]}
}}
}}
])
See how it works on the playground example
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论