[SERVER-35535] The aggregate pipe stops if $match has no results Created: 11/Jun/18  Updated: 27/Oct/23  Resolved: 21/Jun/18

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: 4.0.0-rc4
Fix Version/s: None

Type: Improvement Priority: Minor - P4
Reporter: Dmitry Assignee: Nick Brewer
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Participants:

 Description   

db.blacklist.aggregate([
  { $project: { contact: 1, profile: 1 } },
  { $match: { contact: 'SELF_ID_STR' }, // * if we not have result, pipe stay on whis step.
  // convert results to { _id: null, blocked_list: [idslist...] }
  { $group: { _id: null, blocked_list: { $push: { $toObjectId: '$profile' } } } },
  {
    $lookup: {
      from: 'profiles',
      as: 'profiles',
      let: { ignore: '$blocked_list' },
      pipeline: [
        // * cant use $nin in aggregate
        // * cant modify results for add self profile to exclude
        { $match: { $expr: { $not: { $in: ['$_id', '$$ignore'] } } } }
      ]
    }
  },
  { $unwind: '$profiles' },
  { $replaceRoot: { newRoot: '$profiles' } }
]);



 Comments   
Comment by Nick Brewer [ 21/Jun/18 ]

focus-at,

By definition, $match will ensure that only the documents that meet your match criteria are passed to the next aggregation pipeline stage; if nothing matches, no documents are passed along to the next stage. It seems like you're essentially trying to use $match as a "not equal to" to remove documents meeting a specific criteria from the results that are passed to the next stage in the pipeline. This is certainly possible, but you need to use the $ne operator. For example, if I have a collection with the following documents:

> db.test.find()
{ "_id" : ObjectId("5b2be1cb11c2cd0a7a9bb795"), "name" : "dave" }
{ "_id" : ObjectId("5b2be1d311c2cd0a7a9bb796"), "name" : "robert" }
{ "_id" : ObjectId("5b2be1d811c2cd0a7a9bb797"), "name" : "michelle" }

I could use the following $match with $ne to ensure that documents with a name value of "dave" are not passed to the next stage in the pipeline:

db.test.aggregate(
[
   {
       $match:
       {
           "name": {$ne: "dave"}
       }
    }
 ]
)

Regards,
Nick

Comment by Dmitry [ 11/Jun/18 ]

i do query to empty collection 

$match stage results = []

$group stage result = [] (not grouped)

but i need execute $lookup with ignored ids from $group stage

way of adding a document to the result after $match stage ?

 

Comment by Kelsey Schubert [ 11/Jun/18 ]

Hi focus-at,

What do you mean when you say the aggregation pipe "stops"? Would you please clarify why behavior or output would you like to see if a aggregation stage does not pass any documents to the next stage?

Thank you,
Kelsey

Generated at Thu Feb 08 04:40:09 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.