不存在的mongodb(减去两个查询结果)
假设我有以下收藏不存在的mongodb(减去两个查询结果),mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,假设我有以下收藏 [ { "user_id": 7, "action": 1 }, { "user_id": 8, "action": 1 }, { "user_id": 9, "action": 1 }, { "user_id": 7, "action": 2 } ] 我需要找到所有有例如操作1但没
[
{
"user_id": 7,
"action": 1
},
{
"user_id": 8,
"action": 1
},
{
"user_id": 9,
"action": 1
},
{
"user_id": 7,
"action": 2
}
]
我需要找到所有有例如操作1但没有操作2的用户。
在mysql中,可以通过两个查询选择user_id并减去结果,或者使用where not exists子查询
我如何处理mongodb的问题
因此,我的预期结果是:
[8,9]
您可以使用聚合管道首先将所有操作分组到一个数组中,再将关联的用户id分组到对象中,并使用过滤器使操作
1
,而不是2
,然后仅保留id:
db.collection.aggregate([
// group user id and all actions together
{
$group: {
_id: "$user_id",
actions: {
$addToSet: "$action"
}
}
},
// filter documents which have 1 as action but not 2
{
$match: {
$and: [
{
"actions": 1
},
{
"actions": {
$not: {
$eq: 2
}
}
}
]
}
},
// only keep the id
{
$group: {
_id: "$_id"
}
}
])
这将返回:
[
{
"_id": 8
},
{
"_id": 9
}
]
以下是一个playgorund的链接:
你应该考虑如何构造你的文档。您的设计看起来有点像关系数据库。建议根据您的读取权限(如果可能)对文档进行建模。在这种情况下,您可以使用一个
用户id
和一个操作
字段,该字段已经将所有操作id分组在一起。您可以使用聚合管道首先将所有操作分组到一个数组中,然后将关联的用户id组合到对象中,并使用过滤器使操作1
,而不是2
,然后只保留id:
db.collection.aggregate([
// group user id and all actions together
{
$group: {
_id: "$user_id",
actions: {
$addToSet: "$action"
}
}
},
// filter documents which have 1 as action but not 2
{
$match: {
$and: [
{
"actions": 1
},
{
"actions": {
$not: {
$eq: 2
}
}
}
]
}
},
// only keep the id
{
$group: {
_id: "$_id"
}
}
])
这将返回:
[
{
"_id": 8
},
{
"_id": 9
}
]
以下是一个playgorund的链接:
你应该考虑如何构造你的文档。您的设计看起来有点像关系数据库。建议根据您的读取权限(如果可能)对文档进行建模。在这种情况下,您可以使用一个用户id
和一个操作
字段,该字段已经将所有操作id分组在一起。您可以对不同的用户id
使用和推送操作
。最后,将$match
与操作一起使用
变量为1,但不等于($ne
)变量为2
您可以对不同的用户id
使用和操作。最后,将$match
与操作一起使用
变量为1,但不等于($ne
)变量为2
谢谢,我认为两个答案都是正确的,所以我选择了第一个答案。是的,但您不需要在这里使用两个
$group
阶段。只需使用$project
,因为我们已经在第一个$group
阶段找到了不同的用户id
。我已经更新了答案。即使它的运营商更少。您不需要在此处使用$group
,$和,$not
聚合。谢谢,我认为两个答案都是正确的,所以我选择了第一个答案。是的,但您不需要在此处使用两个$group
阶段。只需使用$project
,因为我们已经在第一个$group
阶段找到了不同的用户id
。我已经更新了答案。即使它的运营商更少。您不需要在此处使用$group
,$和,$not
聚合。