I am currently facing a small problem with a client-side Collection Update. I can bare the usual 403: Not permitted. Untrusted code may only update documents by ID. and I do understand why it is so, and I am fine with it.
Unfortunately Meteor seems to be too strict on the _id rulecheck and does not allow such query to pass. I have worked around it using method calls but I’d rather directly use the update for latency compensation and easier code.
I do not want to hack my way through, so is there a possibility to loosen the _id check to allow updates that are even more precise than using just an id?
I’m not sure I see the advantage to allowing this… You are already updating by the _id which is a unique index. You couldn’t possibly have another document with that _id so the second key is necessary.
The usual mongo query (at least that I am aware of, not so much an expert yet) to update the finished field of the sheet3.csv element is to use this query:
The only other way I know of doing this is to find() the whole document to fetch the elements array, loop through it to find the correct filename, apply the modification and save the whole element array again. This seems quite heavy compared to using a mongoDB query alone.
Which would work, because mongo IDs are unique, which means you target only one document. All you have to do is obtain the _id of the document that matches {"elements.filename":"sheet3.csv"} first, and then execute your update.
This throws “The positional operator did not find the match needed from the query” this is to be expected as we cannot use the $ operator as we didn’t include any lookup in the query.
I’ll paste the interesting parts of the documentation to help figure out what I’m trying to do:
The positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array.
When used with update operations, e.g. db.collection.update() and db.collection.findAndModify(), the positional $ operator acts as a placeholder for the first element that matches the query document, and the array field must appear as part of the query document.
Since you already know what the document looks like, and you have obtained the _id, can you specify the position in the array to update? Something along these lines:
let index = 2
Datasources.update({
_id:obj.id
},{
$set:{"elements." + index + ".finished":true}
});
Yes that would be a way to go around the problem. That would require me to implement a way to loop through all the elements array to find the one with the correct filename.
Another way to go around it, as I posted above is to simply run the query server-side, which I do and prefer as it is a lot less error-prone. But I have to work out on latency compensation and all that.
Although it is not a blocking problem, I think that this should get addressed or at least assessed as this is only one example of a couple other update queries that could potentially get blocked.
Imagine if I was looking for a $geoinstersect inside my array instead of just a string. That would become very tedious to implement…
Actually, I hadn’t even tried as I was expecting to receive the same error anyways… But it does work. I have rarely used client-side methods as most of the mongo queries I could just run directly.
That’ll do the trick. Not sure though if it closes the subject of allowing more fields in the query, but it sure fixes my problem.