MongoDB: find и findOne с фильтрацией вложенных массивов
Эта маленькая задача оказалась сложнее, чем я думал.
Рассмотрим следующую очень простую коллекцию сообщений. Предположим, я хочу отобразить все сообщения в сочетании только с теми комментариями, которые не были удалены.
IE отфильтровывает удаленные комментарии из массива комментариев.
Поскольку у меня есть 100 удаленных комментариев на пост, есть ли способ сделать это на стороне сервера?
Коллекция:
{
"author": {},
"message": "This is post1",
"comments": [
{
"message": "Im number 1!!!",
"state": {
"deleted": false
}
},
{
"message": "YOU MOTHERF****R",
"state": {
"deleted": true
}
},
{
"message": "tHIS IS GREAT!",
"state": {
"deleted": false
}
},
{
"message": "I can type better than you guys",
"state": {
"deleted": false
}
}
]
},
{
"author": {},
"message": "This is post 2",
"comments": [
{
"message": "This is bulls**t",
"state": {
"deleted": true
}
},
{
"message": "YOU MOTHERF****R",
"state": {
"deleted": true
}
},
{
"message": "I hate u!",
"state": {
"deleted": true
}
},
{
"message": "I wanna have your children",
"state": {
"deleted": false
}
}
]
}
1 ответ
Я буду TL;DR, поскольку это оказалось адской поездкой. я пробовал $elemMatch
, Я пробовал $redact
(также с $$CURRENT и $$ROOT), я попробовал $map
Я пробовал структуру агрегации, я пробовал $project
,
Вы можете прочитать все об этом здесь: https://www.devsbedevin.com/mongodb-find-findone-with-nested-array-filtering-finally/
TL;DR
Похоже, что решение состоит в том, чтобы использовать структуру агрегации для фильтрации массива и переопределить свойство comments результатами. Это проще, чем кажется:
db.getCollection('posts').aggregate(
{$match: {"author.id": authorId}},
{$addFields : {"comments":{$filter:{ // We override the existing field!
input: "$comments",
as: "comment",
cond: {$eq: ["$$comment.state.deleted", false]}
}}}}
);
Результат:
{
"author": {},
"message": "This is post1",
"comments": [
{
"message": "Im number 1!!!",
"state": {
"deleted": false
}
},
{
"message": "tHIS IS GREAT!",
"state": {
"deleted": false
}
},
{
"message": "I can type better than you guys",
"state": {
"deleted": false
}
}
]
},
{
"author": {},
"message": "This is post 2",
"comments": [
{
"message": "I wanna have your children",
"state": {
"deleted": false
}
}
]
}