Ошибка агрегации MongoDB $ in нуждается в массиве - PullRequest
1 голос
/ 27 марта 2020

Ниже приведен мой документ, и я хочу отфильтровать все эти почтовые индексы вместе с соответствующими 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"

Ответы [ 2 ]

0 голосов
/ 28 марта 2020

Поскольку у вас есть 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

0 голосов
/ 28 марта 2020

попробуйте это:

  db.find(
       { zipcode: { $in: [ "10451", "10458", "10467", "10461", "10462" ] } }
    )
...