Фильтрация только тех документов, у которых ВСЕ ПОЛЯ не равны нулю (со структурой агрегирования) - PullRequest
1 голос
/ 04 мая 2020

У меня много документов, но я хочу выяснить, как получить только те документы, у которых ВСЕ ПОЛЯ не равны нулю.
Предположим, у меня есть следующие документы:

[
 {
  'a': 1,
  'b': 2,
  'c': 3
 },
 {
  'a': 9,
  'b': 12
 },
 {
  'a': 5
 }
]

Таким образом, выполняется фильтрация только документов. первые имеют ВСЕ ПОЛЯ не нуль. Так что отфильтровывая эти документы, я бы получил только первое. Как я могу это сделать?

1 Ответ

1 голос
/ 05 мая 2020

Поэтому, когда вы хотите получить только документы, которые имеют ВСЕ ПОЛЯ , без указания всех их в фильтре, например: { a: {$exists : true}, b : {$exists : true}, c : {$exists : true}}, тогда это может быть не очень хорошей идеей, технически иначе если у вас есть 10 полей в документе, то было бы неплохо упомянуть все из них в запросе. В любом случае, поскольку вы не хотите перечислять их все - мы можем попробовать этот хак, если он работает хорошо, скажем, если у вас фиксированная схема и скажите, что все ваши документы могут содержать только поля a, b & c (_id является значением по умолчанию и исключительным), но ничего кроме этих попробуйте:

Если вы можете получить общее количество полей, мы можем проверить количество полей, которое говорит все поля существуют, что-то вроде ниже:

db.collection.aggregate([
  /** add a new field which counts no.of fields in the document */
  {
    $addFields: { count: { $size: { $objectToArray: "$$ROOT" } } }
  },
  {
    $match: { count: { $eq: 4 } } // we've 4 as 3 fields + _id
  },
  {
    $project: { count: 0 }
  }
])

Тест: mongoplayground

Примечание: Мы только проверка на наличие полей, но не проверка на ложные значения, такие как null или [] или '' для полей. Также это может не сработать для вложенных полей.

На всякий случай, если вы хотите проверить, что все поля существуют в документе с их именами, поэтому, если вы можете передать все имена полей в качестве входных данных, попробуйте запрос ниже:

db.collection.aggregate([
    /** create a field with all keys/field names in the document */
    {
      $addFields: {
        data: {
          $let: {
            vars: { data: { $objectToArray: "$$ROOT" } },
            in: "$$data.k"
          }
        }
      }
    },
    {
      $match: { data: { $all: [ "b", "c", "a" ] } } /** List down all the field names from schema */
    },
    {
      $project: { data: 0 }
    }
  ])

Тест: mongoplayground

Ссылка: Агрегационный конвейер

Вы можете попытаться использовать объяснение для проверки эффективности ваших запросов.

...