Это распространенное недоразумение процесса запроса. Я подозреваю, что один из ваших документов выглядит следующим образом:
{
"_id" : 0,
"replies" : [
{ "_id" : "R0", status: "rejected"}
,{ "_id" : "R1", status: "approved"}
]
}
Проблема заключается в том, что выполнение find
для массива будет соответствовать любому документу, где, по крайней мере, совпадает одна из записей массива;это НЕ фильтрует результат, чтобы ПРОСТО эти записи. Вот два подхода. С учетом этих настроек данных:
var r =
[
{
"_id" : 0,
"replies" : [
{ "_id" : "R0", status: "rejected"}
,{ "_id" : "R1", status: "approved"}
]
}
,{
"_id" : 1,
"replies" : [
{ "_id" : "R2", status: "rejected"}
,{ "_id" : "R3", status: "rejected"}
]
}
,{
"_id" : 2,
"replies" : [
{ "_id" : "R4", status: "rejected"}
,{ "_id" : "R5", status: "approved"}
]
}
];
Подход 1: Простой, а встроенный массив мал (десятки, а не 100 или 1000 записей.
db.foo.aggregate([
// This will find all docs where ANY of the replies array has AT LEAST ONE
// entry "approved." It will NOT filter just those.
{$match: {"replies.status": "approved"}}
// Now that we have them, unwind and "refilter"
,{$unwind: "$replies"}
,{$match: {"replies.status": "approved"}}
]);
{ "_id" : 0, "replies" : { "_id" : "R1", "status" : "approved" } }
{ "_id" : 2, "replies" : { "_id" : "R5", "status" : "approved" } }
Подход 2: Используйте $filter
, еслимассив очень большой и использование $unwind
создает тысячи документов. Этот подход также полезен для сохранения структуры исходного документа:
db.foo.aggregate([
// This will find all docs where ANY of the replies array has AT LEAST ONE
// entry "approved." It will NOT filter just those.
{$match: {"replies.status": "approved"}}
// To avoid $unwind, directly filter just "approved" and reset the replies
// field back into the parent doc:
,{$addFields: {replies: {$filter: {
input: "$replies",
as: "zz",
cond: { $eq: [ "$$zz.status", "approved" ] }
}}
}}
]);
/*
{
"_id" : 0,
"replies" : [
{
"_id" : "R1",
"status" : "approved"
}
]
}
{
"_id" : 2,
"replies" : [
{
"_id" : "R5",
"status" : "approved"
}
]
}
}