【问题标题】:Filter subdocument array while still returning parent data if empty如果为空,则过滤子文档数组,同时仍返回父数据
【发布时间】:2014-07-01 10:01:40
【问题描述】:

我正在使用这个问题How to filter array in subdocument with MongoDB的方法

它按预期工作,除非数组中没有任何元素与测试匹配。在这种情况下,我只会得到一个没有父数据的空数组。

样本数据

 {
  "_id": "53712c7238b8d900008ef71c",
  "dealerName": "TestDealer",
  "email": "test@test.com",
  "address": {..},
  "inventories": [
      {
          "title": "active",
          "vehicles": [
            {
              "_id": "53712fa138b8d900008ef720",
              "createdAt": "2014-05-12T20:08:00.000Z",
              "tags": [
                 "vehicle"
               ],
               "opts": {...},
               "listed": false,
               "disclosures": {...},
               "details": {...}
           },
           {
              "_id": "53712fa138b8d900008ef720",
              "createdAt": "2014-05-12T20:08:00.000Z",
              "tags": [...],
              "opts": {...},
              "listed": true,
              "disclosures": {...},
              "details": {...}
            }
         ]
     },
     {
         "title": "sold",
         "vehicles": []
     }
  ]
}

努力去做

在我的查询中,我想返回用户(文档)顶级信息(经销商姓名、电子邮件)和一个名为车辆的属性,其中包含“活动”库存中列出的属性设置为 true 的所有车辆.

我走了多远

这是我的查询。 (我使用 Mongoose,但主要使用原生 Mongo 功能)

      {
        $match:
          email: params.username
      }
      {
        $unwind: '$inventories'
      }
      {
        $match:
          'inventories.title': 'active'
      }
      {
        $unwind:
          '$inventories.vehicles'
      }
      {
        $match:
          'inventories.vehicles.listed':
            $eq: true
      }
      {
        $group:
          _id: '$_id'
          dealerName:
            $first: '$dealerName'
          email:
            $first: '$email'
          address:
            $first: '$address'
          vehicles:
            $push: '$inventories.vehicles'
      }

问题

起初,我认为我的查询很好,但是,如果没有车辆被标记为listed,则查询只会返回一个空数组。这是有道理的,因为

      {
        $match:
          'inventories.vehicles.listed':
            $eq: true
      }

不匹配任何内容,但我仍想获取经销商名称以及他的电子邮件

没有车辆匹配时的期望输出

[{"dealerName": "TestDealer", "email": "test@test.com", vehicles : []}]

实际输出

[]

【问题讨论】:

    标签: javascript arrays mongodb mongoose


    【解决方案1】:

    在这种情况下,您可以使用 $redact 而不是 $match,就像这样

    db.collectionName.aggregate({
      $redact:{
        $cond:{ 
           if:{$and:[{$not:"$dealerName"},{$not:"$title"},{$eq:["$listed",false]}, 
           then: "$$PRUNE", 
           else: "$$DESCEND" 
        }
      }
    })
    

    我们需要第一个条件来跳过顶级文档,第二个条件跳过第二级,第三个条件来修剪车辆。 在这种情况下不需要 $unwind

    还有一点:$redact 仅在 2.6 中可用

    【讨论】:

    • 我认为这不会起作用,因为$cond 必须为真才能使根级和第二级达到第三级。此查询将在根级别修剪文档(它具有字段dealerName,因此$condfalse)。唯一可行的方法是删除前两个条件并将listed:true 添加到根和第二级。
    猜你喜欢
    • 2019-01-12
    • 2016-06-01
    • 1970-01-01
    • 2015-02-07
    • 2021-07-13
    • 2020-07-03
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多