Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB-有条件地匹配两个数组_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

MongoDB-有条件地匹配两个数组

MongoDB-有条件地匹配两个数组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,存在以下对象数组: let externalArray = [ { name: "xxx", max: 100, unit: "myUnit" }, { name: "yyy", max: 90, unit: "myUnit" } ] 以及以下mongodb结构: [ { "myList": [ { "name": "xxx", "amount":

存在以下对象数组:

let externalArray = 
[
 { name: "xxx",
   max: 100,
   unit: "myUnit"
 },
 { name: "yyy",
   max: 90,
   unit: "myUnit"
 }
]

以及以下mongodb结构:

[
    {
        "myList": [
            {
                "name": "xxx",
                "amount": 66.3,
                "unit": "myUnit"
            },
            {
                "name": "yyy",
                "amount": 11.6,
                "unit": "myUnit"
            },
            {
                "name": "zzz",
                "amount": 6.9,
                "unit": "myUnit"
            }
        ]
    }
]

如何在聚合中使用$match查询来仅输出myList.amount所对应的对象,因为您要将输入数组与文档中的数组进行比较,所以除了执行
$filter
,您还需要执行一些操作:

db.collection.aggregate([
    /** Unwind (Split array into objects :: total docs = each doc * no.of objects in array of respective doc) */
    {
      $unwind: "$myList"
    },
    /** Iterate on input `externalArray` & check for all conditions. Creates an array field `matches` */
    {
      $addFields: {
        matches: {
          $filter: {
            input: externalArray,
            cond: {
              $and: [ { $eq: [ "$$this.name", "$myList.name" ] },
                { $eq: [ "$$this.unit", "$myList.unit" ] },
                { $lte: [ "$myList.amount", "$$this.max" ] }
              ]
            }
          }
        }
      }
    },
    /** In filter step if it matches with any condition then `matches` will have 1 or more objects from `externalArray` 
     * Excluding all docs where there is no match */
    {
      $match: { matches: { $ne: [] } }
    },
    /** Remove unnecessary field */
    {
      $project: { matches: 0 }
    },
    /** Since we unwind the array - group back all docs based on `_id` */
    {
      $group: { _id: "$_id", myList: { $push: "$myList" } }
    }
  ])
测试:

注意:

在答复中:

  • myList
    数组将只包含来自
    externalArray
    的匹配对象
  • 如果
    myList
    不存在,或者
    myList
    externalArray
    之间不存在匹配对象,则不会看到文档(因此,两个数组之间应该至少有一个匹配对象才能取出文档)

  • 在将外部数组传递到聚合管道之前,可以将其转换为以下结构并用作条件

    我们可以在
    $match
    表达式中使用它来匹配至少有一个匹配项的文档

    [{
      "name": "xxx",
      "amount": {
        "$lte": 100
      },
      "unit": "myUnit"
    },
    {
      "name": "yyy",
      "amount": {
        "$lte": 90
      },
      "unit": "myUnit"
    }]
    
    /*示例js实现*/
    const matchConditions=externalArray.map({name,max,unit})=>({
    名称
    金额:{$lte:max},
    单元
    }))
    
    我们可以在
    $filter
    条件中使用以下内容

    [{
      "$and": [
        { "$eq": ["name", "xxx"] },
        { "$lte"  ["amount", 100 },
        { "$eq": ["unit", "myUnit"] }
      ]
    },
    {
      "$and": [
        { "$eq": ["$$this.name", "yyy"] },
        { "$lte":  ["$$this.amount", 90 },
        { "$eq": ["$$this.unit", "myUnit"] }
      ]
    }]
    
    最后,我们可以使用以下聚合

    db.collection.aggregate([
      {
        $match: {
          myList: {
            $elemMatch: {
              $or: matchConditions
            }
          }
        }
      },
      {
        $addFields: {
          myList: {
            $filter: {
              input: '$myList',
              cond: {
                $or: filterConditions
              }
            }
          }
        }
      }
    ])
    

    不幸的是没有。。。当我尝试动态使用外部数组中的值时…这很有意义,非常感谢!它确实解决了我最初的问题,我将把你的答案标记为正确,但我刚刚意识到我的数据库结构中还有两个类似“myList”的列表。我要把它们全部解开,走同样的步骤吗?但最后我该如何把所有的东西组合起来呢?仅使用_id:“$\u id”似乎不起作用。@andfrst:哦,好的,通常数组和嵌套数组不仅在MongoDB中是一个问题,在编程语言中也是一个问题:-)如果在庞大的数据集上使用,即使这个查询也有点复杂(尝试在初始阶段过滤文档)!除非我们看到数据,否则我们什么都不能说。。也许你可以用示例数据(整个单据)和所需的o/p提出一个新问题-有人可以帮你查询..这是一个非常优雅的解决方案,谢谢。
    db.collection.aggregate([
      {
        $match: {
          myList: {
            $elemMatch: {
              $or: matchConditions
            }
          }
        }
      },
      {
        $addFields: {
          myList: {
            $filter: {
              input: '$myList',
              cond: {
                $or: filterConditions
              }
            }
          }
        }
      }
    ])