我如何将在 $match 阶段内传递给 $in 运算符的每个 ID 限制为仅 4 个元素

Posted

技术标签:

【中文标题】我如何将在 $match 阶段内传递给 $in 运算符的每个 ID 限制为仅 4 个元素【英文标题】:How can i limit each ID i pass to $in operator inside the $match stage to only 4 elements 【发布时间】:2021-12-11 02:09:50 【问题描述】:

我有一个这样的聚合:

            const files = await File.aggregate([
              
                $match:  facilityId:  $in: facilities  
              ,
              
                $sort:  createdAt: 1 
              ,
              
                $project: 
                  file: 0,
                
              
            ])

我想让每个“设施”只返回 4 个文件,我曾经做过类似 facilities.map(id => query(id)) 的事情,但我想在生产环境中加快速度。

使用 $limit 会限制整个查询,这不是我想要的,我尝试在投影阶段使用 $slice 但出现错误:

MongoError: Bad projection specification, cannot include fields or add computed fields during an exclusion projection

如何在单个查询中实现?

集合的架构是:

const FileStorageSchema = new Schema(
  name:  type: String, required: true ,
  userId:  type: String ,
  facilityId:  type: String ,
  patientId:  type: String ,
  type:  type: String ,
  accessed:  type: Boolean, default: false, required: true ,
  file: 
    type: String, //
    required: true,
    set: AES.encrypt,
    get: AES.decrypt
  ,
  sent:  type: Boolean, default: false, required: true ,
,

  timestamps: true,
  toObject:  getters: true ,
  toJSON:  getters: true 
)

我想返回除包含编码为 base64 的加密 blob 的 file 字段之外的所有字段。

另外:我觉得我的方法不正确,我真正想要的是能够一次查询所有设施 ID,但仅限于为每个设施创建的 4 个最新文件,虽然我使用聚合会帮助我实现这一目标,但我开始认为这不是它的完成方式。

【问题讨论】:

使用$matchstage过滤后,可以在“facility”上进行分组,使用$push进行文档堆积。然后,您可以限制在累积的数据范围内 【参考方案1】:

从问题来看,架构尚不清楚。所以我有两个基于两个模式的答案。请使用适合您的方法

#1

db.collection.aggregate([
  
    $match: 
      facilityId: 
        $in: [
          1,
          2
        ]
      
    
  ,
  
    $group: 
      _id: "$facilityId",
      files: 
        $push: "$file"
      
    
  ,
  
    $project: 
      files: 
        $slice: [
          "$files",
          0,
          4
        ],
        
      
    
  
])

Test Here

#2

db.collection.aggregate([
  
    $match: 
      facilityId: 
        $in: [
          1,
          2
        ]
      
    
  ,
  
    $project: 
      facilityId: 1,
      file: 
        $slice: [
          "$file",
          4
        ]
      
    
  
])

Test Here

【讨论】:

我已经编辑了我的问题并添加了架构和一些说明,我现在正在测试你的提议。 感谢您,我成功了,更改管道以返回我感兴趣的所有字段的 4 个元素的数组,并与 $facilityId 分组,我试图接受您的答案作为最终解决方案。

以上是关于我如何将在 $match 阶段内传递给 $in 运算符的每个 ID 限制为仅 4 个元素的主要内容,如果未能解决你的问题,请参考以下文章

如何在mongodb聚合中将动态值传递给$ in

如何将在我的 Javascript 中创建的字符串数组传递给 C# 代码隐藏文件?

如何实现消息传递通知iOS

如何将变量传递给 IN 子句?

通过 FMDB 将数组传递给 sqlite WHERE IN 子句?

React,将在父级创建的引用传递给子级