Mongoose how to paginate with id using $lt

I’m working on a pagination implementation using MongoDB’s aggregation pipeline. Specifically, I want to paginate articles by fetching only documents with _id values less than a given after value (for “load more” behavior). I implemented this using $match with a filter like { _id: { $lt: new ObjectId(after) } }, and it works fine with find() but returns an empty array when applied inside an aggregation pipeline.

Here’s my current pipeline:

const query = after ? { _id: { $lt: new mongoose.Types.ObjectId(after) } } : {};

articleModel.aggregate([
  { $match: query },
  { $sort: { createdAt: -1 } },
  { $limit: 10 },
  {
    $lookup: {
      from: 'users',
      localField: 'owner',
      foreignField: '_id',
      as: 'doctorInfo'
    }
  },
  { $unwind: { path: '$doctorInfo', preserveNullAndEmptyArrays: true } }
]);

This setup results in an empty response, even though there are documents with _id values less than the specified after value. I’m not sure why this is happening since the same logic works perfectly with find() queries.

I initially thought the issue might be with how I’m constructing the $match query, so I hardcoded it like this:

{ _id: { $lt: new mongoose.Types.ObjectId('64f1b28bfaf999c9a7bf3d21') } }

Still, I got an empty array even though documents with _id values less than that one exist in the collection.

I checked if the issue was related to the order of stages in my aggregation pipeline. I also tried moving the $match stage to different positions in the pipeline, but the result remained the same.

I expected the aggregation query to return documents like how it works with find(), but it seems the pipeline doesn’t respect the _id filtering when used with aggregation.

I found this discussion suggesting facet-based pagination, but I’m not sure if that’s the best approach or how exactly to implement it for my use case.