У меня есть документ mongodb, который выглядит примерно так:
{
"id": 1,
"title": "This is the title",
"body" : "This is the body",
"comments": [
{
"email_address": "[email protected]",
"name": "Mirko",
"surname": "Benedetti",
"language": "it",
"text": "This is a message",
"published": "Y",
"on": "2014-03-22 15:04:04"},
{
"email_address": "[email protected]",
"name": "Marc",
"surname": "Surname",
"language": "it",
"text": "Another Message",
"published": "N",
"on": "2014-03-23 15:04:05"}
]
}
И у меня есть такой запрос:
$this->db->collection->find(array('id' => $id, 'language' => $lang, 'comments.published' => 'Y'),
array('comments.name' => 1, 'comments.surname' => 1, 'comments.text' => 1, 'comments.on' => 1, '_id' => 0));
Моя проблема в том, что при выполнении этого запроса mongodb возвращает оба комментария, которые мне не нужны, мне нужно только сообщение с «опубликовано»: «Y».
Я попытался, например, запустить «comments.published» => «что-то», и ни один комментарий не был выбран, что правильно, но если хотя бы один из комментариев имеет
флаг «опубликован» установлен на «Y», оба комментария показаны.
Любая помощь будет приветствоваться.
смотреть на документация $ elemMatch
db.schools.find( { zipcode: "63109" },
{ students: { $elemMatch: { school: 102 } } } )
Вы должны быть осторожны при использовании оператора elemMatch. Во-первых, у него есть два варианта. $ ElemMatch (проекция) & $ ElemMatch (запрос)
Вариант elemMatch (проекция) работает, потому что у вас есть критерии фильтра, которые соответствуют только одному значению в массиве комментариев.
Приведенный ниже запрос будет работать нормально.
find({'_id' : ObjectId("582f2abf9b549b5a765ab380"), comments: { $elemMatch: { language: "it", published : "Y" }}})
Теперь рассмотрим, когда у вас есть более 1 совпадающих значений (два значения с опубликованным статусом ‘Y’) в массивах комментариев, тогда вышеупомянутый запрос не будет работать и вернет только первое совпадающее значение.
В этом случае вам нужно будет использовать $ фильтр, который отфильтрует массив комментариев на основе пройденных критериев фильтра.
aggregate([{
$match: {
'_id': ObjectId("582f2abf9b549b5a765ab380")
}
}, {
"$project": {
"comments": {
"$filter": {
"input": "$comments",
"as": "result",
"cond": {
$and: [{
$eq: ["$$result.language", "it"]
}, {
$eq: ["$$result.published", "Y"]
}]
}
}
}
}
}, {
$project: {
"comments": {
name: 1,
surname: 1,
text: 1,
on: 1
}
}
}])