MongoDB的聚合项目检查,如果数组包含
我有以下文件:MongoDB的聚合项目检查,如果数组包含
{
_id : 21353456,
username : "xy",
text : "asdf",
comments : [
{
username : "User1",
text : "hi",
},
{
username : "User2",
text : "hi1",
},
{
username : "User3",
text : "hi2",
},
{
username : "User4",
text : "hi3",
}
]
}
现在我想要得到的用户名,文本和注释采用聚集和项目。另外,如果comments数组包含用户名“User1”,我也想要一个布尔值。我有这个,但它不起作用。
db.posttest.aggregate(
[
{
$project:
{
username: 1,
text: 1,
comments : 1,
hasComment: { $eq: [ "comments.$.username", "User1" ] },
_id: 0
}
}
]
)
要做到这一点,你需要先unwind
的意见,然后用group
有一个小窍门。如果你想省略_id
,那么你也需要做一个简单的项目。以下是完整的聚合流水线:
db.posttest.aggregate([
{ $unwind : "$comments" },
{ $group : {
_id : "$_id",
username : { $first : "$username" },
text : { $first : "$text" },
comments : { $push : "$comments" },
hasComments : { $max : { $eq : [ "$comments.username", "User1" ] } }
}},
{ $project : { _id : false } }
])
解释如下。
首先,我们需要摆脱一个数组(comments
)。要做到这一点,我们打开记录;它给了我们四条记录:
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User1",
"text" : "hi"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User2",
"text" : "hi1"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User3",
"text" : "hi2"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User4",
"text" : "hi3"
}
}
现在我们可以将所有记录组合成一个应用函数给每个字段。首先,我们需要给出标准,'分组'字段(或一组字段)。在我们的例子中,它仅仅是id:_id: "$_id"
。
然后,对于每个字段,我们需要决定如何将其包含到结果记录中。我们有几个字段:username
,text
和comments
。对于每四条记录,用户名和文本都是相同的,因此我们可以轻松选取其中的任何一条,即$first
或$last
。
comments
然而,是不同的。我们希望保留所有这些,以便我们每个人都退回$push
。
hasComments
这里有点棘手:我们需要检查是否至少有一个comment.username
包含用户名。我们可以在这里使用$eq: [...]
,它会给我们一些数组,例如[true, false, false, false]
或[false, false, true, false]
。我们需要选择哪个值进入结果记录。在这种情况下,我们既不能使用$first
也不能使用$last
。但是,$max
会给我们一个合适的结果。
你有几个可供选择的选项,你可以尝试。
第一个选项$filter
小号comments
阵列username
User1
随后$size
计数没有出现和true
如果尺寸GT大于0别的false
项目布尔值的。
db.posttest.aggregate(
[{
$project: {
username: 1,
text: 1,
comments: 1,
hasComment: {
$gt: [{
$size: {
$filter: {
input: "$comments",
as: "comment",
cond: {
$eq: ["$$comment.username", "User1"]
}
}
}
}, 0]
},
_id: 0
}
}]
)
第二个选择是使用$setIsSubset
集合运算符来检查是否阵列username
User1
是username
列数组值的子集在comments
阵列。
db.posttest.aggregate(
[{
$project: {
username: 1,
text: 1,
comments: 1,
hasComment: {
$setIsSubset: [
["User1"], "$comments.username"
]
},
_id: 0
}
}]
)
谢谢,很好的回答! – user6586661