Optional Lab - Expressions with $project

Hi,
I don’t understand the exercise. What should I count on?
I tried with the following code, but it doesn’t work.
db.movies.aggregate([
{ $match: { writers: { $elemMatch: { $exists: true } } }},
{ $project:{
_id: 0, writers: {
$map: {
input: “$writers”,
as: “writer”,
in: { $arrayElemAt: [ { $split: [ “$$writer”, " (" ] }, 0 ] }
}
}, “cw”: {$setIntersection: ["$cast", “$writers”]}, directors: 1
}
},
{ $match: {cw: {$size: {$gt: 0}}, cw: {$ne: null} }},
{ $project:{
_id: 0, “cwd”: {$setIntersection: ["$cw", “$directors”]}, directors: 1
}
},
{ $match: {cwd: {$size: {$gt: 0}}, cwd: {$ne: null} }},
])

You can help me
I don’t understand where error is?

Hi @Simona_Pansa,

The $project stage works in a way that it passes the documents with requested fields to the next stage in pipeline.
Please check the below documentation for more details on $project stage:

Few things to note here:

Check whether all the fields that we need in our output or for computation in later stages, exists.

  1. Include all the fields that you need in the later stage in the current $project stage.
  2. If you compute a field in one $project stage, you cannot use the computed value in the same $project stage.

I would recommend you to check the output for each stage while you are adding them to the pipeline so that you can see the how your pipeline is building up.

Please feel free to reach out if you have any questions.

Thanks,
Sonali

Hi @Sonali Mamgain

Esercise: “Lab: $unwind”,

I wrote the result, but it’s wrong.

I used the following query:

Hi @Simona_Pansa,

I can check that you have already completed the lab. However, if you have any questions, please feel free to reach out.

Thanks,
Sonali

I am working on the chapter 1, optional lab and I cant seem to find whats the issue. Please provide any suggestions :slight_smile:

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

What is your exact problem?

Do you get errors?

Wrong results?

Post screenshot so that we see what you get.

Hi @Bhargav_Vadlamudi,

Few things to consider here:

  1. I would recommend you to apply the filter to check if cast directors and writers field exists and are not an empty array.

  2. You do not need to project same fields in multiple $project stages. If you have already projected cast, directors and writers field in first project stage, only these fields will get passed on to the next $project stage.

  3. Can you please share what you are trying to do here:

{ $match: { ‘lovedogs.0’ : { $exists : true } } }

Additionally, before applying this $match stage, check the output of the previous project stage.

Please feel free to reach out if you have any questions.

Thanks,
Sonali

Why do I get a number (of .itcount()) if I do the labor_of_love projection in the first $project stage, and another one when doing the same in a new $porject stage?

What do you mean by doing the same in a new $project?

Are you saying that you do the $project stage twice?

Hi @Federico_Ramayo,

I see that you have already completed the Optional Lab. :clap:

Please feel free to reach out if you have any questions.

Thanks,
Sonali

No, what I mean is that doing this
db.movies.aggregate([ {$match:...}, {$project:.<First project stage>..}, {$project: {labor_of_love: <laborOfLoveExpression>}}, {$match:...}, {$count:...} ]);
I get the right number. But if I do:
db.movies.aggregate([ {$match:...}, {$project:.<One project stage with {labor_of_love: <laborOfLoveExpression>}>..}, {$match:...}, {$count:...} ]);
I get another number.

If you are getting 1259 as the answer, make sure that in the split operation, the second parameter is " (" with a space before the open parenthesis.

1 Like

The reason for that (and I had the same problem as you) is that if you bundle everything up in one single $project stage, you don’t get correct data when the stage is executed. Consider this (wrong) stage:

       $project: {
           cast: 1,
           directors: 1,
           writers: {
               $map: {
                   input: "$writers",
                   as: "writer",
                   in: {
                       $arrayElemAt: [{
                           $split: ["$$writer", " ("]
                       },
                           0
                       ]
                   }
               }
           },
           common: { $setIntersection: ["$writers", "$directors", "$cast"] }
       }

The value of writers filed will only be updated after this stage is done, not during its execution. So when common is “calculated” some strings in writers will not have been pre-processed yet and have from of “Name Lastname (contribution)”, thus leading to wrong intersection result. You (and I) must use additional $project stage to use updated value of writers

Can some please explain why is this not working, i mean i am getting wrong answer?

        var pipeline = [
          {
            "$project" : {
              "writers" : {
                "$map" : {
                  "input": "$writers",
                  "as": "writer",
                  "in": {
                    "$arrayElemAt": [
                      {
                        "$split": ["$$writer", "("]
                      },
                      0
                    ]
                  }
                }
              },
              "cast": 1,
              "directors": 1,
              "_id": 0,
            }
          },
          {
            "$project" : {
              "common": {
                "$setIntersection": ["$writers", "$cast", "$directors"]
              }
            }
          },
          {
            "$project" : {
               "count": {
                "$cond": {
                  "if": {
                    "$isArray": "$common"
                  },
                  "then": {
                    "$size": "$common"
                  },
                  "else": 0
                }
              }
            }
          },
          {
            "$match": {
              "count": {
                "$gt": 0
              }
            }
          },
          {
            "$count": "labours of love"
          }
        ]

i know i should filter the fields first using a match pipeline but i am doing something similar using if/else conditionals below. so why don’t i get the right answer?
@Sonali_Mamgain

Hi @sathya_reddy,

I can check that you were able to complete the Optional Lab. :clap:

If you still have any questions, please feel free to reach out.

Kind Regards,
Sonali