MongoDB Aggregation Project检查数组是否包含 [英] MongoDB Aggregation Project check if array contains
问题描述
我有以下文件:
{
_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"的用户名,我还需要一个布尔值.我有这个,但是不起作用.
Now I want to get the username, text and comments with aggregation and project. In addition I also want a boolean if the comments array contains an username with "User1". I have this, but it doesn't work.
db.posttest.aggregate(
[
{
$project:
{
username: 1,
text: 1,
comments : 1,
hasComment: { $eq: [ "comments.$.username", "User1" ] },
_id: 0
}
}
]
)
推荐答案
要实现此目的,您需要先unwind
注释,然后使用带有一些技巧的group
.如果要省略_id
,则还需要做一个简单的项目.这是完整的聚合管道:
To achieve this you would need to first unwind
the comments, and then use a group
with a little trick. If you want to omit the _id
, then you would also need to do a simple project. Here is the full aggregation pipeline:
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
).为此,我们释放记录.它给了我们四个记录:
First, we need to get rid of an array (comments
). To do this we unwind the record; it gives us four records:
{
"_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"
.
Now we can group all the records into one applying a function to each field. First, we need to give criteria, the 'group by' field (or set of fields). In our case, it is simply the id: _id: "$_id"
.
然后,对于每个字段,我们需要决定如何将其包含到结果记录中.我们只有几个字段:username
,text
和comments
.对于每四个记录,用户名和文本都是相同的,因此我们可以轻松地选择它们中的任何一个,即$first
或$last
.
Then, for each field, we need to make a decision on how to include it into the resulting record. We have few fields: username
, text
, and comments
. For each four records the username and text are the same, so we can easily pick any of them, namely $first
or $last
.
comments
是不同的.我们想保留所有这些,以便我们每个人都返回$push
.
comments
, however, are different. We want to preserve all of them so that we $push
each one back.
这里的hasComments
有点棘手:我们需要检查是否至少有一个comment.username
包含用户名.我们可以在这里使用$eq: [...]
,它将为我们提供一些数组,例如[true, false, false, false]
或[false, false, true, false]
.我们需要选择将哪个值记入结果记录中.在这种情况下,我们不能使用$first
或$last
.但是,$max
将为我们提供适当的结果.
The hasComments
is a bit tricky here: we need to check if at least one comment.username
contains the username. We can use $eq: [...]
here, it will give us some array, e.g. [true, false, false, false]
or [false, false, true, false]
. We would need to pick which value goes into the resulting record. In this case, we can use neither $first
nor $last
. However, $max
will give us an appropriate result.
这篇关于MongoDB Aggregation Project检查数组是否包含的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!