我正在尝试计算具有不同条件的文档。这里我有这样简化的文本表(文档):
{
"teamId": "1",
"stage": "0",
"answeredBy": [userId_1, userId_2],
"skippedBy": [userId_3],
"answers": []
},
{
"teamId": "1",
"stage": "0",
"answeredBy": [userId_2],
"skippedBy": [userId_1],
"answers": []
},
{
"teamId" : "1",
"stage": "0",
"answeredBy": [userId_3],
"skippedBy": [userId_2],
"answers": []
},
{
"teamId" : "1",
"stage": "1",
"answeredBy": [userId_3],
"skippedBy": [userId_1, userId_2],
"answers": [
{ "readBy": [userId_1] },
{ "readBy": [userId_1, userId_2] },
{ "readBy": [userId_3, userId_1] },
]
},
{
"teamId" : "1",
"stage": "1",
"answeredBy": [userId_3],
"skippedBy": [userId_1, userId_2],
"answers": [
{ "readBy": [userId_1] },
{ "readBy": [userId_1, userId_2] },
{ "readBy": [userId_3] },
]
};
我想对每个适当的用户ID,阶段和teamID进行一次查询(因此,第一个$ match必须是每个teamId和阶段:“ 0”或“ 1”:
因此,我尝试了多种方法来实现它,但是最困难的部分是遍历数组 answers 的嵌套数组( readBy ),并找出哪个不不会包含适当的用户,并将此文档视为未读。
可能的结果:
{
answered: 2,
unanswered: 1,
unread: 1,
};
或
[
{ _id: 'answered', count: 2 },
{ _id: 'unanswered', count: 1 },
{ _id: 'unread', count: 1 }
]
编写此查询后,我陷入了困境,不知道如何遍历readBy数组:
db.texts.aggregate([
{ $match: {teamId: 1, $or: [{currStage: 0}, {currStage: 1}]}},
{ $project: { 'stage': { $switch: { branches: [
{ case:
{ $and: [ { $eq: [ '$currStage', 0 ] },
{ $not: [ { $or: [ { $in: [ userId_1, '$answeredBy' ] },
{ $in: [ userId_1, '$skippedBy' ] } ] } ] } ] },
then: 'unanswered'},
{ case:
{ $and: [ { $eq: [ '$currStage', 0 ] },
{ $or: [ { $in: [ userId_1, '$answeredBy' ] },
{ $in: [ userId_1, '$skippedBy' ] } ] } ] },
then: 'answered'},
{ case:
{ $and: [ { $eq: [ '$currStage', 1 ] },
{ $not: [ { $in: [ userId_1, '$answers.readBy' ] } ] } ] },
then: 'unread'},
] } } } },
{ $group: { _id: '$stage', count: { $sum: 1 } } },
]);
答案 0 :(得分:1)
尝试一下,我假设userid = userId_1
db.getCollection('answers').aggregate([
{ $match: {teamId: '1', $or: [{stage: '0'}, {stage: '1'}]}},
{$project:{
counts :{$cond: [
{$or:[{$in:["userId_1", "$answeredBy"]}, {$in:["userId_1", "$skippedBy"]}]},
{$literal:{answered: 1, unaswered: 0}},
{$literal:{answered: 0, unaswered: 1}}
]},
unread : {$cond:[
{$gt:[{$reduce: {
input: "$answers",
initialValue: 1,
in: {$multiply:["$$value",
{$cond:[
{$in:["userId_1", "$$this.readBy"]},
{$literal: 0},
{$literal: 1}
]}
]}}},
0
]},
{$literal: 1},
{$literal: 0}
]}
}},
{$group: {_id: null, answered: {$sum: "$counts.answered"}, unanswered: {$sum: "$counts.unanswered"}, unread: {$sum: "$unread"}}}
])
答案 1 :(得分:0)
这是我的工作解决方案。谢谢所有尝试解决它并为我提供帮助的人。
db.test.aggregate([
{ $match: {teamId: "1", $or: [{stage: "0"}, {stage: "1", "answers": {$elemMatch: {"readBy": {$nin: ["userId_1"]}}}}]}},
{ $project: { 'stage': { $switch: { branches: [
{ case:
{ $and: [ { $eq: [ '$stage', "0" ] },
{ $not: [ { $or: [ { $in: [ "userId_1", '$answeredBy' ] },
{ $in: [ "userId_1", '$skippedBy' ] } ] } ] } ] },
then: 'unanswered'},
{ case:
{ $and: [ { $eq: [ '$stage', "0" ] },
{ $or: [ { $in: [ "userId_1", '$answeredBy' ] },
{ $in: [ "userId_1", '$skippedBy' ] } ] } ] },
then: 'answered'},
{ case:
{ $eq: [ '$stage', "1" ] } ,
then: 'unread'},
] } } } },
{ $group: { _id: '$stage', count: { $sum: 1 } } },
])
也许我应该找到一个更好的解决方案,但是目前这是我所需要的。