mongodb不存在的地方(减去两个查询结果)

时间:2018-11-16 09:06:58

标签: 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但没有操作2的用户。 在mysql中,可以只选择带有两个查询的user_id并减去此结果,或者使用不存在的子查询。

我怎么用mongodb处理呢?

所以我的预期结果是:

[8,9]

2 个答案:

答案 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 }
])