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

Time:10-27

I have an aggregate like this :

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

And i would like to have each "facility" return only 4 files, i used to do something like facilities.map(id => query(id)) but id like to speed things up in production env.

Using $limit will limit the whole query, that's not what i want, i tried using $slice in the projection stage but got en error :

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

how can i achieve that in a single query ?

Schema of the collections is :

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 }
})

And i would like to returns all fields except for the file fields that contains the encrypted blob encoded as base64.

Also: i have the feeling that my approach is not correct, what i really would like to get is being able to query all facilityId at once but limited to the 4 latest file created for each facility, i though using an aggregate would help me achieve this but im starting to think it's not how its done.

CodePudding user response:

From the question the schema is not clear. So I have two answers based on two Schemas. Please use what works for you

#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

  • Related