2

I have a Meteor method that I call from the client, which in turn updates all fields in a single document. In the last line of code below I try to immediately run the same update on the client to get the immediate side effects (it assumes the update will go through). The trouble is I get:

update failed: Access denied. In a restricted collection you can only update documents, not replace them. Use a Mongo update operator, such as '$set'

when trying to do that. I don't want to update a single field, I want to update the whole document. Is there a way to do this properly?

entry = {
    title: title
    text: text
    tags: entry.tags
    mode: $('#mode').val()
    file_ids: entry.file_ids
}

eid = Session.get('entryId')
entry._id = eid if eid

context = Session.get('context')
Meteor.call('saveEntry', title, entry, context)
Entries.update({_id: entry._id}, entry)
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
funkyeah
  • 3,074
  • 5
  • 28
  • 47
  • Can you elaborate on the 'saveEntry' method? You could just run update as part of that method which would avoid your issue. – user728291 May 28 '14 at 04:23
  • yes, you are correct... see my comment added below the other answer, the secret here is stub methods as you alluded – funkyeah May 28 '14 at 15:30

1 Answers1

5

Do something like:

Entries.update({_id: entry._id}, { $set: entry })

A typical update request is on the form:

Collection.update(
   <query>,
   <update>
)

From the Mongodb documentation, about updating with a regular key:value object:

Replace Document Entirely

If the document contains only field:value expressions, then:

  • The update() method replaces the matching document with the document. The update() method does not replace the _id value. For an example, see Replace All Fields.
  • update() cannot update multiple documents.

and about updating specific fields, using $set, $inc etc.:

Update Specific Fields

If the document contains update operator expressions, such as those using the $set operator, then:

  • The document must contain only update operator expressions.
  • The update() method updates only the corresponding fields in the document. For an example, see Update Specific Fields.

And additionally, as I can understand, from your error message Meteor don't allow replacing whole documents entirely, from the client side. So an option is to use the $set operator and set all the values, which in this case is the whole document itself. You may typically skip adding the _id key to your document before passing it to the $set operator.

Bjørn Bråthen
  • 410
  • 8
  • 20
  • Unfortunately for meteor specifically your solution doesn't seem to work. Minimongo does not support it. The solution I ultimately ended up using was to move my original Entries.update call into a client side meteor method named saveEntry. For whatever reason if you actually do the update from a stub it works. I don't want to not select your answer so if you could add this detail to your solution I'd prefer to mark you as correct. – funkyeah May 28 '14 at 06:11
  • ok, so do I understand you correctly, you wrapped the update call inside a method inside Meteor.methods(), like so: https://gist.github.com/anonymous/2387816 ? – Bjørn Bråthen May 28 '14 at 19:00
  • sort of... my understanding is you can have Meteor.methods on both the server and the client. One can do a full collection update on the client as long as it is within a client side Meteor.method – funkyeah Jun 04 '14 at 06:12