Why these two aggregate generates different itcount()

query 1:

db.movies.aggregate([ 
	{
		'$match': { 
			'cast': { $elemMatch: { $exists: true	}	},
			'directors': { $elemMatch: { $exists: true	}	},
			'writers': { $elemMatch: { $exists: true	}	}
		}
	},
  	{
		'$project': {
			'_id': 0,
			'cast': 1 ,
			'directors': 1,
			'writers': {
				$map: {
					input: "$writers",
					as: "writer",
					in: {
						$arrayElemAt: [ { $split: [ "$$writer", " (" ] }, 0	]
					}
				}
			},
			'persons': {
				'$setIntersection': [ '$cast', '$directors', '$writers']
			}

		}
	},
    {
        '$project': { 
            'labor_of_love': { 
                '$gt' : [ 
                    {$size: '$persons' }
                    , 0 
                ] 
            }
        }
    },
   	{
		'$match': { 
			"labor_of_love": true
		}
	}
])

query 2:

db.movies.aggregate([ 
	{
		'$match': { 
			'cast': { $elemMatch: { $exists: true	}	},
			'directors': { $elemMatch: { $exists: true	}	},
			'writers': { $elemMatch: { $exists: true	}	}
		}
	},
  	{
		'$project': {
			'_id': 0,
			'cast': 1 ,
			'directors': 1,
			'writers': {
				$map: {
					input: "$writers",
					as: "writer",
					in: {
						$arrayElemAt: [ { $split: [ "$$writer", " (" ] }, 0	]
					}
				}
			}
		}
	},
	{
		'$project': { 
			'labor_of_love': { 
				$gt : [ 
					{$size: { 
						$setIntersection: [	"$cast", "$directors", "$writers"] 
						}	
					}
					, 0 
				] 
			}
		}
	},
   	{
		'$match': { 
			"labor_of_love": true
		}
	}
])

Because in the first case the $writers you use for $setIntersection is still the one at the beginning of the stage. The $map you are doing will only be in the next stage.

Thanks for point this subtle sequencing effect. The execution of $map seems taking place but is not until projection is carried out. Great point!

2 Likes