代码之家  ›  专栏  ›  技术社区  ›  Majid Abdolhosseini

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

  •  1
  • Majid Abdolhosseini  · 技术社区  · 7 年前

    我有以下的收藏,

    [
    
        {
            "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]
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   mbuechmann    7 年前

    您可以使用聚合管道首先将所有操作分组到一个数组中,再将关联的用户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分组在一起。

        2
  •  2
  •   Ashh    7 年前

    你可以用 $group $push actions 为了明确 user_id . 最终使用 $match 行动 $eq $ne

    db.collection.aggregate([
      { "$group": {
        "_id": "$user_id",
        "actions": { "$push": "$action" }
      }},
      { "$match": { "actions": { "$eq": 1, "$ne": 2 }}},
      { "$project": { "_id": 1 }
    ])
    
    推荐文章