Запрос проекции MongoDB, поле фильтра в соответствующем элементе внутреннего массива

У меня есть документ, содержащий массив. Вот так:

"_id" : ObjectId("55101f81e4b07caf8554b9b1"),
"myId" : "1222222",
"isDelayed" : false,
"status" : "BALLS",
"yellow" : false,
"white" : true,
"people" : [ 
    {
        "peopleId" : 222222,
        "bc" : 0,
        "status" : "live",
        "fc" : 1,
        "tc": 4,
        "rc": "yellow" 

    }, 
    {
        "peopleId" : 33312,
        "bc" : 0,
        "status" : "live",
        "fc" : 1,
        "tc": 4,
        "rc": "yellow" 

    }, 
  ...

У меня есть запрос mongo, как показано ниже, в коллекции mycoll, если myId=1.222, и в массиве людей, если people.peopleId=1123 он возвращает первое совпадение:

db.getCollection('mycoll').find(
    {myId:'1.222',
        people: { $elemMatch: { peopleId: 1123 }
                 }
    },{"people.$": 1 }).pretty();

Результат включает все поля в записи людей из массива:

"people" : [ 
        {
            "peopleId" : 1122,
            "bc" : 0,
            "status" : "live",
            "fc" : 1,
            "tc": 4,
            "rc": "yellow" 

        }, 

Как мне отфильтровать ответ о том, что он возвращает только нужное поле из записи соответствия во внутреннем массиве, например "status"? Я могу создать фильтр для внешнего документа, но не для поля в элементе массива.


person user1843591    schedule 09.04.2015    source источник


Ответы (2)


Вы можете сделать это с помощью агрегирования. Что вам нужно сделать:

  1. Сопоставьте документы с желаемым myId.
  2. Размотайте people массивы, чтобы внутри people был один документ на каждый вложенный документ.
  3. Соответствует указанному peopleId.
  4. Поля проекта по желанию.
db.mycoll.aggregate([
    { "$match": { "myId": "1.222"} },
    { "$unwind": "$people" },
    { "$match": { "people.peopleId": 1123 }},
    { "$project": { "peopleId": "$people.peopleId",
                    "status": "$people.status" }
    }
]).pretty();
person Juan Carlos Farah    schedule 09.04.2015

Монго $ elemMatch в проекции используется в проекции для определения конкретного поля в ваш случай status под запросом возвращает только status поле

db.collectionName.find({"myId":"1222222"},{"people":{"$elemMatch":{"peopleId":33312}},"people.status":1}).pretty()
person Yogesh    schedule 09.04.2015
comment
Привет @yogesh, да, но это вернет 'status' для всех элементов массива, а не только для соответствующего - person user1843591; 09.04.2015
comment
@ user1843591 Я думаю, вы должны что-то потерять, это показывает мне точный результат совпадения status результат, как показано ниже {"_id" : ObjectId("55101f81e4b07caf8554b9b1"),"people" : [{"status" : "live"}]} - person Yogesh; 09.04.2015
comment
вы правы, мои извинения, это «выглядело» как моя попытка, но я на самом деле не пробовал. спасибо за ваш ответ, я собираюсь отметить ответ @juancarlos как правильный, поскольку его решение вернет точные совпадения (все критерии), тогда как это решение вернет `` пустой '' результат для всех записей, которые соответствуют myId: 1222222 даже если $ elemMatch ничего не возвращает. - person user1843591; 09.04.2015