mongodb聚合查询$filter不支持$exists问题

需求场景

在mongodb聚合查询中,有时为了把返回结果压缩简化到最小,可能会对array数组字段本身的元素进行过滤,例如数组字段viewList中包含多个view,希望返回结果的viewList中只包含那些view.permissionSetting非空的。

很自然的想到$filter运算符来实现:

[{$match: {
  "viewList.permissionSetting":{$exists:1},
}}, 
 {$project: {
  viewList: {
    $filter:{
      input:"$viewList",
      as:'item',
      cond:{$and:[
        {$exists:"$$item.permissionSetting"},
        {$gt:[{$size:"$$item.permissionSetting.userIdList"}, 0]}
        ]}
    }
  },
}}, 
 {$match: {
  viewList:{$ne:[]}
}}]

但是很不幸,这个会报错Unrecognized expression '$exists'

原因是$filter中不支持$exists,

本需求的viewList过滤规则恰好是根据其中元素的某个字段存在与否来过滤,

如果不能用filter+exists实现,那就只能用$unwind先把viewList展开,后再做match筛选,然后再group聚合恢复展开前的样子,貌似也可以实现,但是这个运行效率和代码复杂度就一言难尽了。

外网搜到一个技巧可以绕过——以{$ne:[{$type:"$$item.permissionSetting"}, "missing"]} 判断字段存在。

https://stackoverflow.com/questions/74989480/mongodb-filter-an-array-of-objects-with-exists

[{$match: {
  "viewList.permissionSetting":{$exists:1},
}}, 
 {$project: {
  viewList: {
    $filter:{
      input:"$viewList",
      as:'item',
      cond:{$and:[
        {$ne:[{$type:"$$item.permissionSetting"}, "missing"]},
        {$gt:[{$size:"$$item.permissionSetting.userIdList"}, 0]}
        ]}
    }
  },
}}, 
 {$match: {
  viewList:{$ne:[]}
}}]

你可能感兴趣的:(mongodb)