0

I am trying to update the object inside the document

Document: Cats

{
        "_id": "5e5cb512e90bd40017385305",
        "type": "cat"
        "history": [
          {
            "id": "randomID",
            "content": "xyz",
          },
          {
            "id": "randomID2",
            "content": "abc",
          }
        ]
}

Code to select and update the object inside the history array:

const editHistory = async (_, { input }, ctx) => {
  let query = { _id: input.catId, "history.id": input.historyId };
  let update = { $set: { "history.$": input.history } };
  let options = {
    new: true,
    fields: { history: { $elemMatch: { id: "randomID" } } }
  };

  let cat = await ctx.models.cats.findOneAndUpdate(query, update, options);

  return cat;
};

Input has following values

input: {
catId: "5e5cb512e90bd40017385305",
historyId: "randomID",
history: {
id: "randomID",
content: "new content"
}}

I tried using Projection, I used select changed it to field, found in mongoose documentation. I still couldn't update the values. Is there anything wrong with the way i am querying or selecting the subfield.

10
  • id (document) or _id (query) ? Commented Apr 24, 2020 at 23:46
  • Its _id for Cat document and id for history array obejcts Commented Apr 24, 2020 at 23:56
  • What happens when you run findOne with the same query? Commented Apr 25, 2020 at 0:00
  • It just returns the Cat Document Commented Apr 25, 2020 at 0:47
  • @mickl is there a way I can solve this? Commented Apr 25, 2020 at 2:54

1 Answer 1

1

Found the Solution for it by going through more detail of the operator($set) and option(new, fields).

Question:

const editHistory = async (_, { input }, ctx) => {
  let query = { _id: input.catId, "history.id": input.historyId };
  let update = { $set: { "history.$": input.history } };
  let options = {
    // using new option would return the new document
    new: true, 
    /* using fields option would select the based on the given key, but using new: 
       true with fields will throw error: 'cannot use a positional projection and 
   return the new document'
   */
    fields: { history: { $elemMatch: { id: "randomID" } } } 
  };

  let cat = await ctx.models.cats.findOneAndUpdate(query, update, options);

  return cat;
};

This post below answers that question for *error: 'cannot use a positional projection and return the new document'.

https://stackoverflow.com/a/46064082/5492398

Final Solution:

const editHistory = async (_, { input }, ctx) => {
  let query = { _id: input.catId, "history.id": input.historyId };
  let update = { $set: { "history.$": input.history } };
  let options = {
    new: true
  };

  let cat = await ctx.models.cats.findOneAndUpdate(query, update, options);

  return cat;
};

Removing field option, since I don't need the unmodified selection before atomic modification, solves the question.

Sign up to request clarification or add additional context in comments.

Comments

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.