2

I know this is a duplicate question. But I have hit the same road block a lot of other seem to hit in updating nested arrays. I am able to manually code an index value, but obviously thats not useful in practical api deployment. So can arrayFilters be used on an array with a length of 1? should i restructure the prospect model, and revert this to a subdocument? Any help would be great.

the console Error

MongoError: No array filter found for identifier 'elem' in path 'resoStatus.representation.$[elem].document'

The document in mongo

:
Object_id:5f15a5fe911928412c858fb0
name:"State POA"
postedDate:2020-07-19T05:56:19.738+00:00
assigned:5efd0c3d75bb7122943e3a49

req.params.id: 5f15a5fe911928412c858fb0

the function that doesnt work

router.put(
  "/:id/resoStatus/representation/:id",
  upload,
  auth,
  async (req, res) => {
    console.log(req.params.id);
    const prospect = await Prospect.findOneAndUpdate(
      { "_id": req.body.prospectId },
      {
        "$set": {
          "resoStatus.representation.$[elem].document": req.file.filename,
          "resoStatus.representation.$[elem].updatedDate": req.file.uploadDate,
          "resoStatus.representation.$[elem].id": req.body.id,
        },
        upsert: true,
        arrayFilters: [{ "elem._id": ObjectID(req.params.id) }],
      },
      (err) => {
        if (err) res.status(400).json(err);
      }
    );

    console.log(prospect.resoStatus.representation);
    res.status(200).json(prospect);
  }
);

the function that does work

router.put(
  "/:id/resoStatus/representation/:id",
  upload,
  auth,
  async (req, res) => {
    console.log(req.params.id);
    const prospect = await Prospect.findOneAndUpdate(
      { "_id": req.body.prospectId },
      {
        "$set": {
          "resoStatus.representation.0.document": req.file.filename,
          "resoStatus.representation.0.updatedDate": req.file.uploadDate,
          "resoStatus.representation.0.id": req.body.id,
        },
        upsert: true,
        arrayFilters: [{ "elem._id": ObjectID(req.params.id) }],
      },
      (err) => {
        if (err) res.status(400).json(err);
      }
    );

    console.log(prospect.resoStatus.representation);
    res.status(200).json(prospect);
  }
);

the mongoose model

 representation: [
      {
        document: String,
        name: String,
        postedDate: Date,
        id: String,
        updatedDate: Date,
        endpoint: String,
        assigned: { type: mongoose.Schema.Types.ObjectId, ref: "user" },
      }]

1 Answer 1

4

You can use the $-operator to update the first element that matches the query document:

"$set": {
          "resoStatus.representation.$.document": req.file.filename,
          "resoStatus.representation.$.updatedDate": req.file.uploadDate,
          "resoStatus.representation.$.id": req.body.id,
        }

If you need to update all array elements of the matched document, you can use the all-positional operator:

"$set": {
          "resoStatus.representation.$[].document": req.file.filename,
          "resoStatus.representation.$[].updatedDate": req.file.uploadDate,
          "resoStatus.representation.$[].id": req.body.id,
        }
Sign up to request clarification or add additional context in comments.

4 Comments

so this will match all or the first with object id?
i guess elem is something that is hard coded in someone elses schema and gets carried over. I assumed you just needed to sort of map the object as it were. but removing elem with just a blank [] worked! Man is it ever all down hill from here. :D
No, both queries match the exact same document, i.e. the document that matches the filter { "_id": req.body.prospectId }. Option 1 then updates the first element in the array that satisfies the conditions (filename, date, id). The second one updates all array-elements.
Happy to help, please accept the answer. Thank you! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.