У меня есть документ в моем экземпляре mongo в нижнем формате,
{
"_id" : "08d4a242-08fb-07f7-46e5-8717a81d5b70",
"fname" : "john",
"created_date" : ISODate("2017-05-24T01:13:06.829Z"),
"customProp" : [
[
"customX","{\"some data related to X \"}"
],
[
"customY","{\"some data related to Y \"}"
],
[
"customZ","{\"some data related to Z \"}"
]
]
}
элементы/значения, такие как "customX", "customY" и "customZ", необязательно должны быть во всех документах. Как получить все значения во втором элементе массива "customProp", в этом документе содержится "customZ"?
Я могу использовать следующий запрос для фильтрации и поиска всех документов, имеющих элемент "customZ",
db.getCollection('col1').find({$and : [{"customProp":{$elemMatch:{0:"customZ"}}}, {"created": { $gte: ISODate("2017-05-22T00:00:00.000Z") }}] },{"created":1}).limit(1) .pretty()
выход:
{
"_id" : "08d4a242-08fb-07f7-46e5-8717a81d5b45",
"created" : ISODate("2017-05-24T01:13:06.829Z")
}
но найти способ получить все значения во втором элементе массива, где первым значением является "customZ".
ожидаемый результат:
{
"_id" : "08d4a242-08fb-07f7-46e5-8717a81d5b45",
"created" : ISODate("2017-05-24T01:13:06.829Z"),
"customPro": ["customZ","{\"some data related to Z \"}"]
}
Я в порядке, если мой запрос просто вернется
{
"{\"some data related to Z \"}"
}
Ну, это вложенный массив, который не является отличной идеей, но вы фактически сопоставляете элемент с выражением $elemMatch
, так что вы получаете позицию во внешнем массиве customProp
, что позволяет проецировать с позиционным $
operator:
db.getCollection('coll1').find(
{
"customProp":{ "$elemMatch": { "0": "customZ" } },
"created_date": { "$gte": ISODate("2017-05-22T00:00:00.000Z") }
},
{ "created_date": 1, "customProp.$": 1 }
)
Это дает результат:
{
"_id" : "08d4a242-08fb-07f7-46e5-8717a81d5b70",
"created_date" : ISODate("2017-05-24T01:13:06.829Z"),
"customProp" : [
[
"customZ",
"{\"some data related to Z \"}"
]
]
}
Где customProp
конечно, все еще находится в вложенном массиве, но при обработке отдельных документов на python вы можете просто получить доступ к свойству в индексе массива:
doc['customProp'][0][1]
Который, конечно, возвращает значение:
'{"some data related to Z "}'
То же самое можно сказать о JavaScript, который в основном идентичен синтаксису. В качестве примера оболочки:
db.getCollection('coll1').find(
{
"customProp":{ "$elemMatch": { "0": "customZ" } },
"created_date": { "$gte": ISODate("2017-05-22T00:00:00.000Z") }
},
{ "created_date": 1, "customProp.$": 1 }
).map(function(doc) {
doc['customProp'] = doc['customProp'][0][1];
return doc;
})
И выход:
{
"_id" : "08d4a242-08fb-07f7-46e5-8717a81d5b70",
"created_date" : ISODate("2017-05-24T01:13:06.829Z"),
"customProp" : "{\"some data related to Z \"}"
}
И позиционный $
project здесь гарантирует, что в возвращенном массиве есть только один элемент, поэтому нотация всегда будет одинаковой для извлечения из всех результатов документа. Таким образом, вы получаете согласованный элемент из базы данных, и вы извлекаете свойство через код.
Также обратите внимание, что вам не нужно $and
здесь, поскольку все аргументы запроса уже являются условиями И. Это значение по умолчанию для MongoDB, поэтому вам не нужно явно его выражать. Посмотрите, насколько лучше это выглядит без него.