Updating an object within array

I have the following structure of my Invoices collection:

{
    patient_id: ...',
    insurance_id: ...,
    services: [
        {service_id: 'consultation', service_name: 'Consultation', service_price: 1000},
        {service_id: 'rct', service_name: 'Root Canal Therapy', service_price: 12000},
        {service_id: 'rcf', service_name: 'Root Canal Finishing', service_price: 3500}
    ],
    ...
}

I’d like to update one of the objects within the services array. How would I go about doing this?

Well, you either pull the document and replace it completely or you try to do this (which should work if MiniMongo supports it).

Haven’t tried it myself, though.

Collection.update({_id: your_document_id, "services.service_id": "rct"}, {$set: { "services.$.service_name" : "Panama Canal Therapy" } });

And I do hope that you have your local data protection laws in mind. Healthcare is quite a sensitive area.

1 Like

I’m getting this error when I try the update method:

allow-deny.js:494 Uncaught Error: Not permitted. Untrusted code may only update documents by ID.

I guess I can’t do that on the client. I’ll just have to pull the doc and replace. Will that make the app slow though?

Yeah. I’m really concerned about the security part. Being a little bit green with Meteor, I’m not sure how exactly to tackle that, but I’m yet to do my research on the matter.

Use Meteor.methods - then you can do anything you want. Which you should do anyway for security reasons.

Basically, do not manipulate (i.e. update/insert/delete) any documents clientside at all. Do stuff like that only through Meteor.methods.

1 Like

Hi,

Nested anything in mongo is a pain. Or maybe I just don’t understand projections very well… The pattern I use is:

const <someConst> = <someCollection>.findOne({ _id: id }); // assuming you have id for the top level

// Index 1
const aIndex = <theFirstIndex> // do whatever to find the array index for level 1

// Index 2
const bIndex = <theSecondIndex> // do whatever to find the array index for level 2

let setModifier = { $set: {} };
setModifier.$set[
  'services.'+ aIndex + '.service_name.' + bIndex + '.<someThingElse>'
] = <whateverItShouldBe>; // Assume the array has 2 levels of nesting
// hence aIndex and bIndex... the dot-notation is used to specify the array element index

<someCollection>.update({ _id: id }, setModifier);

I can never do my searches nicely with the projections like the examples show, and then manipulate the data super efficiently. Hence my noob method.

Thanks so much.

Tat

Edit: Basically i don’t trust my code when using projections in mongo. So I work it out manually and go from there…

That’s actually what the $ in {$set: { "services.$.service_name" : is for. It remembers the index of the array subset you’re searching for.

In essence, my one line of code does exactly what you’re doing in 8 lines and a lot more code.

Sure - i hear what you are saying. But how do you specify what the $ should be? Like I understand what you are saying, just can’t work out how to do it. If you could stick up an example of doing a search in a nested object array, it would be most appreciated.

Thanks in advance.

Tat

The example is up there. You search through an array (that’s what "services.service_id": "rct" is for) and then $stands for the index of the array’s position for the result.

hmm… I get what you are saying. I’m not sure fully, so am playing with it. Thanks for taking the time to walk me through it. I think i’ll try some stuff and then understand it better. Thanks so much.

Hiya, bumping into this thread because I’m facing the same issue.

I don’t seem to make @rhywden’s solution work.

In my methods file :
Carts.update({_id : cartId, "items.$.id" : productId}, { ... });
is executed, returns a 200, but my collection is not updated.

Any idea what could cause this ?

My bad. Problem solved.

I had an extra $ in my operator so be careful :

Collection.update({"items.id" : ...}, { ... });

hey guys,
i am having a doubt,i want to update all the objects in an array with a unique id. i tried this,but all the objects are getting same id,but i want all objects with unique id’s
my code:collection.update({“Finra Rules.Part.Subparts”:{"$type":“array”}},{"set":{"Finra Rules.Part.[].id":ObjectId()}})

please reply,
regards
aswin``