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

How can i limit each ID i pass to $in operator inside the $match stage to only 4 elements

我有这样的聚合:

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

而且我希望每个“设施”return 只有 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 }
})

而且我想 return 除了包含编码为 base64 的加密 blob 的 file 字段之外的所有字段。

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

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

#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