过滤子文档数组,同时仍返回父数据(如果为空)

Nic*_*ise 2 javascript arrays mongoose mongodb

我正在使用此问题中的方法如何使用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": []
     }
  ]
}
Run Code Online (Sandbox Code Playgroud)

想要做

在我的查询中,我想返回用户(文档)顶级信息(dealerName,电子邮件)和一个名为vehicle的属性,其中包含列出属性设置为的"活动"库存中的所有车辆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'
      }
Run Code Online (Sandbox Code Playgroud)

问题

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

      {
        $match:
          'inventories.vehicles.listed':
            $eq: true
      }
Run Code Online (Sandbox Code Playgroud)

什么都不匹配,但我仍然希望获得dealerName以及他的电子邮件

如果没有车辆匹配,则希望输出

[{"dealerName": "TestDealer", "email": "test@test.com", vehicles : []}]
Run Code Online (Sandbox Code Playgroud)

实际输出

[]
Run Code Online (Sandbox Code Playgroud)

And*_*nyi 5

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

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

我们需要第一个条件来跳过顶级文件,第二个条件跳过第二个级别,第三个条件来修剪车辆.在这种情况下不需要$展开!

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