Вы можете сделать это, используя агрегационный конвейер MongoDB :
Различные способы сделать это. Один из способов - использовать $unwind
:
Тип 1 - Запрос 1:
db.collection.aggregate([
/** Optional but will be good on huge collections to lessen data for further stages */
{
$match: { "survey_user.user_option.option_id": "O12" }
},
{
$unwind: "$survey_user"
},
/** When you unwind a each object/element in array gets it's own document after `unwind` stage */
{
$match: { "survey_user.user_option.option_id": "O12" }
},
/** After match you'll only have objects which met the criteria in `survey_user` array */
/** group on `_id` & push entire original doc to data field */
{
$group: { _id: "$_id", survey_user: { $push: "$survey_user" }, data: { $first: "$$ROOT" } }
},
/** Add `survey_user` array to `data.survey_user` & it's size to `data.optedCount` field */
{
$addFields: { "data.survey_user": "$survey_user", "data.optedCount": { $size: "$survey_user" } }
},
/** Make `data` as new root to doc */
{
$replaceRoot: { newRoot: "$data" }
}
])
Тест: mongoplayground
На всякий случай, если вам нужен только подсчет, но не нужен для всего do c, который должен быть возвращен, в приведенном выше запросе будут небольшие изменения:
Тип 1 - Запрос 2:
db.collection.aggregate([
{
$match: { "survey_user.user_option.option_id": "O12" }
},
{
$unwind: "$survey_user"
},
{
$match: { "survey_user.user_option.option_id": "O12" }
},
/** Just group on `_id` & count no.of docs, maintain `survey_id` */
{
$group: { _id: "$_id", optedCount: { $sum: 1 }, survey_id: { $first: "$survey_id" } }
}
])
Тест: mongoplayground
Использование итератора массива $reduce
, что может быть полезно, если данные ваших коллекций настолько велики, что раскрутка взорвет ваши документы.
Тип 2 - Запрос:
db.collection.aggregate([
{
$match: {
"survey_user.user_option.option_id": "O12",
},
},
/** Instead of `$addFields`, you can use `$project` to project fewer needed fields (which can be help improve query with performance benefits ) */
{
$addFields: {
optedCount: {
$reduce: {
input: "$survey_user",
initialValue: 0,
in: {
$cond: [
{ $in: ["O12", "$$this.user_option.option_id"] },
{ $add: ["$$value", 1] },
"$$value",
]
}
}
}
}
}
]);
Тест: mongoplayground