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

Posted

技术标签:

【中文标题】如果为空,则过滤子文档数组,同时仍返回父数据【英文标题】: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 : []]

实际输出

[]

【问题讨论】:

【参考方案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 添加到根和第二级。

以上是关于如果为空,则过滤子文档数组,同时仍返回父数据的主要内容,如果未能解决你的问题,请参考以下文章

在聚合管道中过滤数组为空时保留主文档

js过滤数组中都为空的对象几种方式

当过滤器为空时,它返回空数组

「React Native」子组件Render中props为空报错问题

二叉树的下一节点

Java中数组如果为空,则返回一个数,怎么做?