skip to Main Content

for example while performing aggregation the last(previous) stage gave me this documents

{
 _id : ObjectId('662a416201ca2363543b6644'),
 name : 'location-1',
 startsFrom : 2,
 endsOn : 5,
}
{
 _id : ObjectId('662a416201ca2363543b6644'),
 name : 'location-1',
 startsFrom : 1,
 endsOn : 3,
}
{
 _id : ObjectId('662a416201ca2363543b6644'),
 name : 'location-1',
 startsFrom : 2,
 endsOn : 4,
}

the next stage is $match

{
 $match{
  "startsFrom" : { $lte : 2},
  "endsOn" : { $gte : 2},
 }
}

here as after comparison with the first document the match stage results in true . so I want to skip the $match stage for all other documents with same _id as of the document which completed the match stage and got the result true.

If this is not possible is there any other alternate solution to reduce the computation power consumption without changing the previous aggregation stages

NOTE :
documents with same _id after the previous $unwind stage might be
more than 1million and that too for multiple _ids .

2

Answers


  1. You can use a $group stage with an accumulator of $first:

    db.collection.aggregate([
      // start: example "previous stages"
      { $unwind: "$docs" },
      { $replaceWith: "$docs" },
      // end: example "previous stages"
      {
        $match: {
          "startsFrom": { $lte: 2 },
          "endsOn": { $gte: 2 }
        }
      },
      // put a sort here
      {
        $group: {
          _id: "$_id",
          first_doc: { $first: "$$ROOT" }
        }
      },
      { $replaceWith: "$first_doc" }
    ])
    

    Mongo Playground

    In the example above, it selects only one document per _id given; or any field(s)/expression which you pass to { $group: { _id: <expr> } }. In your case, it is the _id field.

    Note: it’s recommended to use a $sort before the group so that you get consistent "first" documents. From the docs:

    Returns the result of an expression for the first document in a group of documents. Only meaningful when documents are in a defined order.

    To define the document order for $first in other pipeline stages, add a preceding $sort stage.

    Login or Signup to reply.
  2. You can try to write your own custom pipe like $matchFirstInGroup:

    For map-reduce operations that require custom functionality, you can
    use the $accumulator and $function aggregation operators. You can use
    those operators to define custom aggregation expressions in
    JavaScript.

    docs

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search