简体   繁体   English

MongoDB 查找字段不存在的所有文档,如果存在则应用字段运算符 ($max) 条件

[英]MongoDB find all docs where field doesn't exists, plus if exists apply field operator ($max) condition

I am looking for a query for a $match stage in my aggregation which do almost the same, as in this question , but..我正在为我的聚合中的$match阶段寻找一个查询,它的作用几乎此问题相同,但是..

  • if field (named rank in my case) doesn't exists in document, add document to results如果文档中不存在字段(在我的情况下命名为排名),则将文档添加到结果中
  • but if field, exists, apply $operator condition (in my case it's $max ) to this field, and add all documents that suits this condition to the results.但是如果字段存在,则将$operator条件(在我的情况下为$max )应用于该字段,并将所有符合此条件的文档添加到结果中。

MongoPlayground with example collection . MongoPlayground 与示例集合

Result should be like this:结果应该是这样的:

[
  {
    "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
  }
]

Things, that I have tried already:我已经尝试过的事情:

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

UPD: As for now, probably I don't limit with $match stage only, $project is also relevant after default match, so I could request every document during $match stage by id no matter, have the doc rank field or not, and then, during $project stage do a "separation" by rank $exists UPD:就目前而言,我可能不仅仅限制$match阶段,默认匹配后$project也是相关的,所以我可以在$match阶段通过id请求每个文档,无论是否具有 doc rank字段,然后,在$project阶段按排名$exists进行“分离”

Try this one:试试这个:

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 Mongo游乐场

I have found an answer, separated from @Valijon's method, but it's also based on the logic above.我找到了一个答案,与@Valijon 的方法分开,但它也是基于上面的逻辑。 My query is:我的查询是:

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"
            ]
          }
        },
      ]
    }
  }
])

My query is based on $project stage which gives the empty field value 0. It also could be -1, or any value that isn't used in collection.我的查询基于$project阶段,它给出空字段值 0。它也可以是 -1,或任何未在集合中使用的值。 And then I separate results.然后我将结果分开。

MongoPlayground Mongo游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM