下面是我的文档,我想过滤所有这些邮政编码以及它们对应的res_count
,它们也存在于名为data
的数组中。
文档:
{ "data" : [ "10451", "10458", "10467", "10461", "10462" ] }
{ "zipcode" : "10470", "res_count" : 8 }
{ "zipcode" : "10454", "res_count" : 10 }
{ "zipcode" : "10466", "res_count" : 11 }
{ "zipcode" : "10455", "res_count" : 9 }
{ "zipcode" : "10462", "res_count" : 29 }
{ "zipcode" : "10461", "res_count" : 25 }
{ "zipcode" : "10467", "res_count" : 15 }
{ "zipcode" : "10465", "res_count" : 28 }
{ "zipcode" : "10452", "res_count" : 11 }
{ "zipcode" : "10469", "res_count" : 10 }
{ "zipcode" : "10459", "res_count" : 7 }
{ "zipcode" : "10457", "res_count" : 14 }
{ "zipcode" : "10451", "res_count" : 68 }
{ "zipcode" : "10463", "res_count" : 28 }
{ "zipcode" : "10458", "res_count" : 34 }
{ "zipcode" : "10468", "res_count" : 12 }
{ "zipcode" : "10475", "res_count" : 14 }
{ "zipcode" : "10474", "res_count" : 10 }
{ "zipcode" : "10473", "res_count" : 3 }
我尝试使用$in
,但它说"errmsg" : "$in needs an array"
尝试一下:
db.find(
{ zipcode: { $in: [ "10451", "10458", "10467", "10461", "10462" ] } }
)
因为您仅在一个文档中具有data
字段。因此,如果在$in
中运行$match
,例如{$match : {$in : ['$zipcode', '$data']}}
,则会抛出相同的错误"errmsg" : "$in needs an array"
。
但是为什么?
[通常,Aggregation pipeline stages对收集文档执行原子操作,因此每个文档都不能使用,因此不能使用一个文档的字段取代其他文档。 (<< [Ex:-如果尝试$addFields
添加从$data
提取的新字段'dataCopy'-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-PlaygroundTest: