2

I wouldnt be surprised if this has been asked before but I have not found a working example.

Basically I have a set of Boolean data inside of an array of objects and I would like to reuse my API routes/logic to update array of objects dynamically

Data Example:

{
    "_id": 1,
    "posts": [
       { "_id": d323d32, "published": true, "homepage": false, (...moreBooleanData) }, 
       { "_id": ffwfwfwc, "published": true, "homepage": false, (...moreBooleanData) },
       { "_id": fdscsdad, "published": true, "homepage": false, (...moreBooleanData) }
    ]
}

Mongoose Query

await Project.findOneAndUpdate(
    { _id: 1 },
    { $set: { "posts.$[el].published": isChecked } },
    {
        arrayFilters: [{ "el._id": postid }],
        new: true
    }
)

The problem is in this line "posts.$[el].published": isChecked. Here I have the key published hard coded but I would like to have this key dynamic so I can grab it from the body of my post request

const { DYNAMIC_KEY , isChecked } = req.body

"posts.$[el].$[DYNAMIC_KEY]": isChecked`

I have tried formatting the $set string with backticks, building it outside the query and passing it as 1 variable all without success. Any ideas?

1 Answer 1

2

You can achieve this using bracket notation:

router.post("/project/:id/:postid", async (req, res) => {

  const { isChecked, dynamicKey } = req.body;
  let set = `posts.$[el].${dynamicKey}`;

  console.log(set);

  const result = await Project.findOneAndUpdate(
    { _id: req.params.id },
    { $set: { [set]: isChecked } },
    {
      arrayFilters: [{ "el._id": req.params.postid }],
      new: true
    }
  );

  res.send(result);
});

I have a project document with these 3 posts:

{
    "_id" : ObjectId("5def81070066dc23e05b816e"),
    "posts" : [
        {
            "_id" : ObjectId("5def81070066dc23e05b8171"),
            "published" : true,
            "homepage" : false
        },
        {
            "_id" : ObjectId("5def81070066dc23e05b8170"),
            "published" : true,
            "homepage" : false
        },
        {
            "_id" : ObjectId("5def81070066dc23e05b816f"),
            "published" : true,
            "homepage" : false
        }
    ],
    "__v" : 0
}

I send a post request to my router ../project/5def81070066dc23e05b816e/5def81070066dc23e05b8170 with this body:

{
  "isChecked": false,
  "dynamicKey": "published"
}

The result is like this: ( post's (with id 5def81070066dc23e05b8170) published value is updated to false)

{
    "_id": "5def81070066dc23e05b816e",
    "posts": [
        {
            "_id": "5def81070066dc23e05b8171",
            "published": true,
            "homepage": false
        },
        {
            "_id": "5def81070066dc23e05b8170",
            "published": false,
            "homepage": false
        },
        {
            "_id": "5def81070066dc23e05b816f",
            "published": true,
            "homepage": false
        }
    ],
    "__v": 0
}
Sign up to request clarification or add additional context in comments.

1 Comment

This might be the best answer Ive seen in terms of how thorough it was. Thank you very much, I had something similar to this before but I did not have my built string wrapped in brackets like you did here { $set: { [set]: isChecked } }. Thanks again

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.