MongoDB: в чем разница между $ elemMatch и $ и поиском объектов внутри массива? - PullRequest
0 голосов
/ 15 октября 2019

Существует ли логическая разница между использованием оператора запроса $and

db.collection.find({$and: [{"array.field1": "someValue"}, {"array.field2": 3}]})

и использованием оператора проецирования $elemMatch

db.collection.find({array: {$elemMatch: {field1: "someValue", field2: 3}}})

для поиска документов, которыесодержать поля объекта внутри массива?

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Я объясню это на примере. Рассмотрим коллекцию arrays. В нем есть поле с именем arr, которое представляет собой массив вложенных документов (с полями a и b).

Некоторые документы в коллекции arrays:

{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 2, "arr" : [ { "a" : "a1", "b" : "b11" }, { "a" : "a2", "b" : "b22" } ] }
{ "_id" : 3, "arr" : [ { "a" : "a2", "b" : "b1" }, { "a" : "a", "b" : "b1" } ] }
{ "_id" : 4, "arr" : [ { "a" : "a1", "b" : "b91" }, { "a" : "a29", "b" : "b1" } ] }

Я хочу найти все документы с полями встроенного документа массива a="a1" AND b="b1". Обратите внимание, что это должно быть в том же элементе встроенного документа массива. Я использую $ elemMatch для этого и получаю желаемый результат.

> db.arrays.find( { arr: { $elemMatch: { a: "a1", b: "b1" } } } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }

Теперь, если я использую операторы $ и , как в следующем запросе, результатыне правильно. Как видите, дополнительный документ выбран. Запрос работал с массивом полей встроенного документа a="a1" ИЛИ b="b1".

> db.arrays.find({$and: [ { "arr.a": "a1" }, { "arr.b": "b1" } ] } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 4, "arr" : [ { "a" : "a1", "b" : "b91" }, { "a" : "a29", "b" : "b1" } ] }

Таким образом, использование оператора $and НЕ предназначено для этой цели (т. Е. Запросов к нескольким полям массива поддокументов).

Кроме того, для запроса к полю встроенного документа массива ( только одно поле ) $elemMatch не требуется, например:

> db.arrays.find( { "arr.a": "a2" } )
==>
{ "_id" : 1, "arr" : [ { "a" : "a1", "b" : "b1" }, { "a" : "a2", "b" : "b2" } ] }
{ "_id" : 2, "arr" : [ { "a" : "a1", "b" : "b11" }, { "a" : "a2", "b" : "b22" } ] }
{ "_id" : 3, "arr" : [ { "a" : "a2", "b" : "b1" }, { "a" : "a", "b" : "b1" } ] }
1 голос
/ 15 октября 2019

Ваш первый запрос найдет документы, в массиве которых есть хотя бы один элемент с field1 = somevalue и хотя бы один элемент с field2 = 3. Оба элемента могут быть разными. Второй будет извлекать документы, в которых массив имеет хотя бы один элемент, соответствующий двум условиям одновременно. Вот пример данных для объяснения:

   {
    array: [
      {
        field1: 1,   
      },
      {
        field2: 2
      },
      {
        field1: 1,
        field2: 3
      },
    ]
  },
  {
    array: [
      {
        field1: 1,
        field2: 2
      },
      {
        field2: 3
      }
    ]
  },
  {
    array: [
      {
        field1: 1,
        field2: "other"
      },
      {
        field2: 2
      }
    ]
  }

Первый запрос

db.collection.find ({"array.field1": 1, "array.field2": 2}) (эквивалентно вашему $ и синтаксису)

возвратит три документа,

db.collection.find ({массив: {$ elemMatch: {поле1:1, field2: 2}}})

вернет только второй документ (единственный, имеющий элемент, соответствующий обоим критериям)

EDIT: логический оператор первого запросаИЛИ, для второго - И, на уровне элемента массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...