不存在的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
聚合。