首页 > 解决方案 > MongoDB 聚合错误 $in 需要一个数组

问题描述

下面是我的文档,我想过滤所有这些邮政编码以及它们对应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"

标签: mongodbmongodb-queryaggregation-framework

解决方案


由于您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-游乐场


推荐阅读