考虑到我有以下收藏,
[
{
"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并减去此结果,或者使用不存在的子查询。
我怎么用mongodb处理呢?
所以我的预期结果是:
[8,9]
答案 0 :(得分:3)
您可以使用聚合管道将所有操作首先分组为一个数组,然后将关联的用户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的链接:https://mongoplayground.net/p/So4HjEXx3sn
您应该考虑如何构造文档。您的设计看起来有点像关系数据库。建议根据您的读取访问权限对文档进行建模(如果可能)。在这种情况下,您可以创建一个user_id
和一个actions
字段,该字段已经将所有操作ID分组在一起。
答案 1 :(得分:2)
您可以将$push
的{{3}}和 actions
用于不同的user_id
。最后,将 $match
与actions
$eq
均使用1,但不等于( $ne
)到2
db.collection.aggregate([
{ "$group": {
"_id": "$user_id",
"actions": { "$push": "$action" }
}},
{ "$match": { "actions": { "$eq": 1, "$ne": 2 }}},
{ "$project": { "_id": 1 }
])