Updating an object within array


#1

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?


#2

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.


#3

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.


#4

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.


#5

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…


#6

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.


#7

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


#8

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.


#9

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.


#10

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 ?


#11

My bad. Problem solved.

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

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


#12

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``