【问题标题】:MongoDB find all docs where field doesn't exists, plus if exists apply field operator ($max) conditionMongoDB查找字段不存在的所有文档,加上如果存在则应用字段运算符($ max)条件
【发布时间】:2020-08-09 00:30:04
【问题描述】:

我正在寻找对我的聚合中的 $match 阶段的查询,它与in this question 的作用几乎相同,但是......

  • 如果文档中不存在字段(在我的例子中名为 rank),则将文档添加到结果中
  • 但如果字段存在,则将$operator 条件(在我的情况下为$max)应用于此字段,并将所有符合此条件的文档添加到结果中。

MongoPlayground with example collection.

结果应该是这样的:

[
  {
    "method": 3,
    "item": 1,
    "rank": 3 //because it has field named rank, and suits condition {rank: $max}
  },
  {
    "method": 4,
    "item": 1 //we need this, because document doesn't have rank field at all
  },
  {
    "method": 5,
    "item": 1 //we need this, because document doesn't have rank field at all
  }
]

我已经尝试过的事情:

            {
                $match: {
                    $or: [
                        {item: id, rank: {$exists: true, $max: "$rank"}}, //id === 1
                        {item: id, rank: {$exists: false}} //id === 1
                    ]
                }
            }

UPD:就目前而言,我可能不仅限于$match 阶段,$project 在默认匹配后也是相关的,所以我可以在$match 阶段通过id 请求每个文档,无论如何,是否有 doc rank 字段,然后在 $project 阶段按等级 $exists 进行“分离”

【问题讨论】:

  • 不清楚您要做什么...在您的示例 + 预期结果中,您跳过前 2 个文档...请提供有效的示例/预期结果...
  • @Valijon 是吗?我想从集合中找到没有特定字段的每个文档,但如果有,则将条件应用于该字段。并且这个条件应该有一个字段操作符。猜猜看,再简单不过了。
  • 现在更清楚了,谢谢。检查我的答案

标签: javascript mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

我找到了一个答案,与@Valijon 的方法分开,但它也是基于上面的逻辑。我的查询是:

db.collection.aggregate([
  {
    $match: {
      item: id
    }
  },
  {
    $project: {
      method: 1,
      item: 1,
      rank: {
        $ifNull: [
          "$rank",
          0
        ]
      }
    }
  },
  {
    $group: {
      _id: "$item",
      data: {
        $addToSet: "$$ROOT"
      },
      min_value: {
        $min: "$rank"
      },
      max_value: {
        $max: "$rank"
      }
    }
  },
  {
    $unwind: "$data"
  },
  {
    $match: {
      $or: [
        {
          $expr: {
            $eq: [
              "$data.rank",
              "$max_value"
            ]
          }
        },
        {
          $expr: {
            $eq: [
              "$data.rank",
              "$min_value"
            ]
          }
        },
      ]
    }
  }
])

我的查询基于$project 阶段,它给出空字段值0。它也可以是-1,或任何未在集合中使用的值。然后我将结果分开。

MongoPlayground

【讨论】:

    【解决方案2】:

    试试这个:

    db.collection.aggregate([
      {
        $match: {
          item: id
        }
      },
      {
        $group: {
          _id: "$item",   //<- Change here your searching field
          max: {
            $max: "$rank" //<- Change here your field to apply $max
          },
          data: {
            $push: "$$ROOT"
          }
        }
      },
      {
        $unwind: "$data"
      },
      {
        $match: {
          $expr: {
            $or: [
              {
                $eq: [
                  {
                    $type: "$data.rank"
                  },
                  "missing"
                ]
              },
              {
                $eq: [
                  "$data.rank",
                  "$max"
                ]
              }
            ]
          }
        }
      },
      {
        $replaceWith: "$data"
      }
    ])
    

    MongoPlayground

    【讨论】:

    • Y,谢谢你,你比我更快/更好,所以我接受它作为答案。此外,我目前正在研究变体,基于$project 阶段和$ifNull
    猜你喜欢
    • 2014-05-26
    • 2022-01-09
    • 2021-04-24
    • 2012-01-23
    • 2015-12-21
    • 1970-01-01
    • 2017-01-20
    • 2016-10-08
    • 1970-01-01
    相关资源
    最近更新 更多