如何在猫鼬节点js中使用聚合来使用多个嵌套对象来过滤多个嵌套数组对象

时间:2019-09-26 22:28:32

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我需要通过使用mongoose nodejs聚合使用多个嵌套对象来过滤多个嵌套数组对象。我提到了来自收集对象和多重过滤器对象的样本记录数据。

我使用一个电子商务产品列表视图页面。在此列表页面中,我们有许多具有不同功能的产品。在这里,我需要使用该产品功能列表来过滤该产品。

示例:

  

我有3部具有不同功能的手机,例如   颜色,RAM,存储。这些功能位于“ productfilter”中   下面的样本收集记录中的数组。我可以选择多个   过滤手机等功能,我选择颜色:蓝色,金色和   内存:6GB,8GB。这里第二个产品来自样品产品清单数据,需要   按照所选过滤器进行获取。因为color:Blue和RAM:6GB是   与第二个产品对象中的“ IsDefault:'true'”匹配   产品清单数据样本

     

这里需要根据过滤器请求数据过滤记录,并需要将“ isDefault”检查为“ true”

样品收集记录

[
  {
    "_id": "5d710f9950b94f237f04407b",
    "productfilter": [
      {
        "_id": "5d8d29ae014da910c0de0799",
        "specTitle": "Color",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de079d",
            "specLabel": "Rose Gold",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-rose-gold-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de079c",
            "specLabel": "Black",
            "isDefault": "true",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-black-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de079b",
            "specLabel": "Blue",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-blue-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de079a",
            "specLabel": "Red",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-red-6gb-64gb-redmi-note-6-pro"
          }
        ]
      },
      {
        "_id": "5d8d29ae014da910c0de0796",
        "specTitle": "RAM",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de0798",
            "specLabel": "4GB",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-black-4gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de0797",
            "specLabel": "6GB",
            "isDefault": "true",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-black-6gb-64gb-redmi-note-6-pro"
          }
        ]
      },
      {
        "_id": "5d8d29ae014da910c0de0794",
        "specTitle": "Storage",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de0795",
            "specLabel": "64GB",
            "isDefault": "true",
            "specContent": ""
          }
        ]
      }
    ]
  },
  {
    "_id": "5d710fe050b94f237f04407e",
    "productfilter": [
      {
        "_id": "5d8d29ae014da910c0de07a3",
        "specTitle": "Color",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de07a7",
            "specLabel": "Rose Gold",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-rose-gold-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de07a6",
            "specLabel": "Black",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-black-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de07a5",
            "specLabel": "Blue",
            "isDefault": "true",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-blue-6gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de07a4",
            "specLabel": "Red",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-red-6gb-64gb-redmi-note-6-pro"
          }
        ]
      },
      {
        "_id": "5d8d29ae014da910c0de07a0",
        "specTitle": "RAM",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de07a2",
            "specLabel": "4GB",
            "isDefault": "false",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-blue-4gb-64gb-redmi-note-6-pro"
          },
          {
            "_id": "5d8d29ae014da910c0de07a1",
            "specLabel": "6GB",
            "isDefault": "true",
            "specContent": "mobiles-accessories-mobiles-redmi-redmi-redmi-note-6-pro-blue-6gb-64gb-redmi-note-6-pro"
          }
        ]
      },
      {
        "_id": "5d8d29ae014da910c0de079e",
        "specTitle": "Storage",
        "attributeOptions": [
          {
            "_id": "5d8d29ae014da910c0de079f",
            "specLabel": "64GB",
            "isDefault": "true",
            "specContent": ""
          }
        ]
      }
    ]
  }
]

从产品列表视图页面的过滤器选项列表中抽样选择的请求数据,以过滤以上记录

{
  "filter": {
    "genericFilter": [
      {
        "specTitle": "Color",
        "specLabel": [
          "Blue",
          "Gold",
          "Rose Gold"
        ]
      },
      {
        "specTitle": "RAM",
        "specLabel": [
          "6GB",
          "8GB"
        ]
      },
      {
        "specTitle": "Storage",
        "specLabel": [
          "64GB",
          "256GB"
        ]
      }
    ]
  }
}

1 个答案:

答案 0 :(得分:0)

可以使用Aggregation Pipeline如下操作

db.products.aggregate([
   {
        $unwind: "$productfilter"
   },
   {
        $unwind: "$productfilter.attributeOptions"
   },
   {
       $project: {
           "specTitle": "$productfilter.specTitle",
           "specLabel": "$productfilter.attributeOptions.specLabel",
           "isDefault": "$productfilter.attributeOptions.isDefault",
           _id:0
       }
   },
   {
       $group: {
           "_id": "$specTitle",
           "specLabel": {$addToSet: "$specLabel"}
       }
   },
   {
    $project: {
        "specTitle": "$_id",
        "specLabel": "$specLabel",
        "isDefault": "$productfilter.attributeOptions.isDefault",
        _id:0
    }
   },
])

说明:

  1. 在第一阶段,查询unwinds数组productFilter;这意味着将文档productFilter数组项的每个值分为多个记录
  2. 在第二阶段,对attributeOptions内的productFilter进行相同操作
  3. Project阶段,保留文档中的相关字段并命名以供以后使用
  4. GroupsspecTitle为止的所有文档,并创建一个新字段'specLabel'(利用$addToSet从所有不同的'specLabel'值组成一个数组。)。因为它是一个集合,所以它不会重复出现的值。
  5. 最后根据需要重组文档。 (这里我没有按示例结果包含过滤器,genericFilter,因为它们是多余的,但是如果您愿意,您可以编辑最后一个阶段$project以适合您的需求