Remove array elements based on values from another array located in the same model

Hey there

Here Is some data from a collection named Questionnaire:

[
  {
    _id: ObjectId("63ea2e2e376ea74c07e96205"),
    sections: [
      {
        questionsIds: [
          "mg7y0aluqkyui487",
          "nonmatchingvaluetoremove"
        ],
        _id: ObjectId("63ea566e7dc0b332cb34c4b1")
      }
    ],
    questions: [
      {
        value: "mg7y0aluqkyui487",
        _id: ObjectId("63ea2e28376ea74c07e961e8"),
      },
      {
        value: "00fbk5o57p9le49q",
        _id: ObjectId("63ea2e28376ea74c07e961e9"),
      }
    ],
  }
]

I am trying to remove from questionsIds only the values that are not exact matching the property “value” from the object array questions.

To do so i tried this:

Questionnaire.updateMany(
	{
		sections: { $exists: true, $ne: [] },
		questions: { $exists: true, $ne: [] },
	},
	{
		$pull: {
			'sections.$[].questionsIds': {
				$nin: '$questions.id',
			},
		},
	},
	{ multi: true, timestamps: false }
)
	.exec();

What happens is that all the elements are being removed from questionsIds, the matching and the non matching elements… Only the non matching ones should be removed.

Any suggestions would be gladly welcome.

Thanks

Here is a playground doing what i want to achieve, I need to find a way to pass $questions.value instead of hardcoded ones: Mongo playground

Using an aggregation pipeline with a $set in your updateOne you may do it with:

filter = { "$filter" : {
    "input" : "$$section.questionsIds" ,
    "as" : "id" ,
    "cond" : { "$in" : [ "$$id" , "$questions.value" ] }
} }
map = { "$map" : {
    "input" : "$sections" ,
    "as" : "section" ,
    "in" : { "$mergeObjects" : [
        "$$section" ,
        { "questionsIds" : filter }
    ] }
} }
Questionnaire.updateMany(
    your_existing_query ,
    [ { "$set" : { "sections" : map } } ]
)

Test doing an aggregation first before updating. Try first

Questionnaire.aggregate( [ { "$set" : { "sections" : map } } ] )

and verify you get what you want.