Подтвердить что ты не робот

Запрос встроенного массива MongoDB

Я спросил это как комментарий к другому вопросу, а также разместил вопрос о пользователе mongodb. Пока нет ответов, поэтому я прибегаю к задаче отдельного вопроса.

documentation:

Если поле содержит массив, то оператор $in выбирает документы, чье поле содержит массив, содержащий хотя бы один элемент, который соответствует значению в указанном массиве (например,, и т.д.)

Я использую:

mongod --version:
db version v2.2.2, pdfile version 4.5
Thu May 30 12:19:12 git version: d1b43b61a5308c4ad0679d34b262c5af9d664267

mongo --version:
MongoDB shell version: 2.0.4

В оболочке MongoDB:

db.nested.insert({'level1': {'level2': [['item00', 'item01'], ['item10', 'item11']]}})

Здесь список запросов, которые должны работать в соответствии с документацией, и результаты, которые они производят:

Почему это не работает?

> db.nested.findOne({'level1.level2.0': 'item00'})
null

Зачем мне нужен $all?

> db.nested.findOne({'level1.level2.0': {'$all': ['item00']}})
{
    "_id" : ObjectId("51a7a4c0909dfd8872f52ed7"),
    "level1" : {
        "level2" : [
            [
                "item00",
                "item01"
            ],
            [
                "item10",
                "item11"
            ]
        ]
    }
}

Как минимум одно из следующего должно работать, правильно?

> db.nested.findOne({'level1.level2.0': {'$in': ['item00']}})
null

> db.nested.findOne({'level1.level2': {'$in': ['item00']}})
null

Любые идеи? Мы рассматриваем отказ от MongoDB, если синтаксис запроса не работает, как рекламируется.

Спасибо!

4b9b3361

Ответ 1

Используйте вложенный elemMatch для поиска вложенных уровней внутри массивов.

Подробнее здесь.

Ответ 2

После выполнения некоторых запросов я пришел к выводу, что $in не работает для массива массивов.

Вместо этого вы можете использовать $elemMatch, и это сработает, но разочарование в том, что документация MongoDB не предупреждает об этом.

Я создал этот документ:

{
      "_id": "51cb12857124a215940cf2d4",
      "level1": [
        [
          "item00",
          "item01"
        ],
        [
          "item10",
          "item11"
        ]
      ],
      "items": [
        "item20",
        "item21"
      ]
}

Обратите внимание, что поле "items" - это массив строк, и этот запрос работает отлично:

db.nested.findOne({"items":{"$in":["item20"]} })

Теперь "level1.0" также представляет собой массив строк, единственное отличие заключается в том, что он находится внутри другого массива. Этот запрос должен работать, но это не так:

db.nested.findOne({"level1.0":{"$in":["item00"]} })

Единственный способ получить результат - использовать $elemMatch:

db.nested.findOne({"level1":{"$elemMatch":{"$in":['item00']}} })

Итак, $elemMatch решает проблему, но реальное решение - обновить документацию MongoDB до состояния, что $in не работает для массивов массивов. Возможно, вы должны отправить запрос на 10gen.

Ответ 3

Короткий ответ: $in - для поля с одним значением, а $all - для массивов.

Во-первых, db.nested.findOne({'level1.level2.0': 'item00'}) не работает, потому что level1.level2.0 содержит массив, и вы пытаетесь сравнить его с одним значением.

Теперь db.nested.findOne({'level1.level2.0': {'$in': ['item00']}}) не работает по той же причине. $in - для сравнения поля с одним значением (у вас есть массив) с несколькими значениями в массиве (указанном в запросе).  $ in говорит: дайте мне документы, у которых есть это поле, значение которого включено в этот массив.

$все работает, потому что говорит: дайте мне документы, у которых есть это поле с несколькими значениями, и все значения этого массива (в запросе) включены в это поле. (Под редакцией)

Невозможно получить, но посмотрите, что говорит документация для каждого:

$все выбирает документы, в которых поле содержит массив и содержит все элементы (e.g. <value>, <value1>, etc.) в массиве.

$выбирает документы, в которых значение поля равно любому значению в указанном массиве (e.g. <value1>, <value2>, etc.)

Надеюсь, что это поможет