MongoDB находит все документы, где поле не существует, плюс, если существует, примените условие оператора поля ($ max) - PullRequest
1 голос
/ 25 апреля 2020

Я ищу запрос для этапа $match в моей агрегации, который почти совпадает с в этом вопросе , но ..

  • если поле (именованное звание в моем случае) не существует в документе, добавить документ к результатам
  • , но если поле существует, применить условие $operator (в моем случае это $max) в это поле и добавьте в результаты все документы, соответствующие этому условию.

MongoPlayground с примером коллекции .

Результат должен быть таким:

[
  {
    "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 независимо от того, есть поле do c rank или нет, а затем На $project этапе делайте «разделение» по рангу $exists

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Попробуйте это:

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

0 голосов
/ 25 апреля 2020

Я нашел ответ, отделенный от метода @ Valijon, но он также основан на логике c выше. Мой запрос:

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

...