Поскольку у вас есть data
поле только в одном документе. Таким образом, если вы запустите $in
в $match
что-то вроде {$match : {$in : ['$zipcode', '$data']}}
, это выдаст ту же ошибку "errmsg" : "$in needs an array"
.
Но почему?
В общем, Этапы конвейерного агрегирования выполняют операции с документами коллекций, обрабатывая каждый документ атомарно, поэтому вы не можете использовать поля одного документ поверх других документов. ( Пример: - Если вы попытаетесь $addFields
добавить новое поле 'dataCopy', взятое из $data
- addFields не добавит новое поле в документы, где поле 'data' не существует). Таким образом, чтобы выполнить эту операцию, вам нужно свести все документы в вашей коллекции в один документ, используя $group
, попробуйте запрос агрегации ниже:
db.collection.aggregate([
/** Iterate on all docs & push document which has 'data' field into 'dataDoc' &
* push all other docs into 'allDocs' array field
*/
{
$group: {
_id: "",
dataDoc: {
$push: {
$cond: [{ $eq: [{ $type: "$data" }, "array"] }, "$$ROOT", "$$REMOVE"]
}
},
allDocs: {
$push: {
$cond: [
{ $eq: [{ $type: "$zipcode" }, "string"] },
"$$ROOT",
"$$REMOVE"
]
}
}
}
},
/** Unwind dataDoc array to make it 'dataDoc' field of type object */
{
$unwind: "$dataDoc"
},
/** Re-create 'allDocs' array field with objects which meet required condition,
* newly formed array will have docs whose zipcode exists in data array
* */
{
$addFields: {
allDocs: {
$filter: {
input: "$allDocs",
cond: { $in: ["$$this.zipcode", "$dataDoc.data"] }
}
}
}
},
/** Unwind 'allDocs' array */
{
$unwind: "$allDocs"
},
/** Make 'allDocs' object field as new root, after this your result will have docs
* whose zipcode exists in data array
*/
{
$replaceRoot: {
newRoot: "$allDocs"
}
}
]);
Тест: MongoDB -Playground