Извлеките два значения подмассива в mongodb с помощью $ elemMatch

Aggregate, $ unwind и $ group не являются моим решением, поскольку они делают запрос очень медленным, поэтому я хочу получить свою запись с помощью метода db.collection.find ().

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

{
    "_id" : 22,
    "scores" : [
        {
            "type" : "exam",
            "score" : 75.04996547553947
        },
        {
            "type" : "quiz",
            "score" : 10.23046475899236
        },
        {
            "type" : "homework",
            "score" : 96.72520512117761
        },
        {
            "type" : "homework",
            "score" : 6.488940333376703
        }
    ]
}

Я выгляжу что-то вроде

db.students.find(
// Search criteria
{ '_id': 22 },

// Projection
{ _id: 1, scores: { $elemMatch: { type: 'exam', type: 'quiz' } }}
)

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

{ "_id": 22, "scores" : [ { "type" : "exam", "type" : "quiz" } ] }  

Но это отменяет тип: 'экзамен' и возвращает только тип: 'викторина'. Кто-нибудь знает, как это сделать с помощью db.find ()?


person Sajjad Ahmed    schedule 16.04.2015    source источник


Ответы (1)


Это невозможно напрямую использовать find и elemMatch из-за следующих ограничений elemMatch и mongo array fields.

Оператор $ elemMatch ограничивает содержимое поля из результатов запроса, чтобы он содержал только первый элемент, соответствующий условию $ elemMatch. исх. из $ elemMacth

и ограничения поля массива mongo, как показано ниже

В документе проекции может присутствовать только один позиционный оператор $.

Документ запроса должен содержать только одно условие для проецируемого поля массива. Несколько условий могут переопределить друг друга внутри и привести к неопределенному поведению. ссылка на ограничения поля массива mongo

Итак, вы либо пытались следить за этим, чтобы узнать только exam или quiz

db.collectionName.find({"_id":22,"scores":{"$elemMatch":{"type":"exam"}}},{"scores.$.type":1}).pretty()

показывает только массив exam оценок.

В противном случае вам следует пройти aggregation

person Yogesh    schedule 16.04.2015
comment
Спасибо за ответ @yogesh, пожалуйста, дайте мне знать, что будет лучшим агрегированием для меньшего времени запроса. - person Sajjad Ahmed; 16.04.2015
comment
проверьте эту stackoverflow.com/questions/2599943/ или использовали индексацию и сегментирование - person Yogesh; 16.04.2015
comment
У меня уже есть индексы, и сегментирование - это не вариант, я пробовал множество вариантов агрегации, но раскрутка делает запрос медленным, поэтому я искал любое решение в find (). - person Sajjad Ahmed; 16.04.2015
comment
@SajjadAhmed, возможно, это поможет вам лучше stackoverflow.com/questions/24018161/ - person Yogesh; 16.04.2015
comment
@SajjadAhmed, чем я могу вам помочь ?? у тебя все еще есть опасения? - person Dineshaws; 17.04.2015
comment
Спасибо за внимание, Динешо, у меня проблема со временем возврата запроса, я пробовал много вариантов в db.find () и aggregation (), но не могу сократить время, затрачиваемое на запросы. Так что, если вы поможете мне найти лучшее решение, я буду очень благодарен. - person Sajjad Ahmed; 17.04.2015
comment
Я использую ** db.collection.find ({date_time: {$ gte: 1428883200000, $ lte: 1429487999000}, device_id: 30, gateway_id: 2}). Sort ({date_time: 1}) **, но это требует От 3 до 5 секунд, что очень много. - person Sajjad Ahmed; 17.04.2015