Developer
Developer

Reputation: 495

MongoError: Unsupported projection option - when using $elemMatch

I have a subject model:

const subjectSchema = new Schema({
  title: String,
  syllabus: {
    currentChapter: {
      heading: String,
      topics: [String],
    },
    chapters: [
      {
        heading: String,
        topics: [String],
      },
    ],
  },
});

I am trying to find a document that corresponds to a particular id. So, I can use:

const subject = await Subject.find({ _id: id });

But now I want that in the chapters array I get only that document that has the heading property equal to "H 1". So I am using $elemMatch (projection).

const subject = await Subject.find(
    { _id: id },
    { syllabus: { chapters: { $elemMatch: { heading: "H 1" } } } }
);

But this is throwing an error.

UnhandledPromiseRejectionWarning: MongoError: Unsupported projection option: syllabus: { chapters: { $elemMatch: { heading: "H 
1" } } }

Upvotes: 0

Views: 721

Answers (2)

Som Shekhar Mukherjee
Som Shekhar Mukherjee

Reputation: 8168

The problem is that you cannot use elemMatch with nested fields.

1) Query the docs that have heading equal to "H1".

Subject.find({_id: id, "syllabus.chapters.heading": "H1"}): This will give all the docs where the chapters array contains at least one object with heading as "H1".

But, here chapters array will contain all the objects present in it.

2) Filter only the matching objects (first matching) from the query condition using the $ positional operator.

The positional $ operator limits the contents of an array to return the first element that matches the query condition on the array. Docs

Subject.find({_id: id, "syllabus.chapters.heading": "H1"}, {"syllabus.chapters.$1": 1}): This will only keep the first matching object where heading is equal to "H1".

Working Solution: Here

Upvotes: 2

kausko
kausko

Reputation: 988

You're passing the $elemMatch condition in the second argument of the find function. You need to move it to the object in the first argument, at the same level as _id: id, and change it to "syllabus.chapters": { $elemMatch: { heading: "H 1" } }.

Here's a working MongoPlayground link

Upvotes: 1

Related Questions