Open fjorgemota opened 8 years ago
Yes, you're right. That inverse is weird. I'll look into that.
The fact that the transaction code just picks up the _id
field shouldn't affect the update part -- as long as the right document is there, the positional operator should be able to do its thing.
For instance:
Items.update({
_id: "a",
"sub_items.id": "b"
}, {
$inc: {
"sub_items.0.freq": 5
}
})
should give an identical result to:
Items.update({
_id: "a"
}, {
$inc: {
"sub_items.0.freq": 5
}
})
[EDIT - No, it shouldn't - see correction of my wrongheadedness in comments below]
The first hash is just about getting the right document to operate on. The second hash is the one that does the updates.
All this said, yes, there's obviously a problem with the update logic. I'll try to figure out why it's not just working out of the box (as it should).
Maybe I have not explained right. But, the query in question is:
Items.update({
_id: "a",
"sub_items.id": "b"
}, {
$inc: {
"sub_items.$.freq": 5
}
})
This is the real query. the sub_items.0.freq
is just what MongoDB understands by finding that sub_items.id = "a"
is in the index 0 of the sub_items
array.
More information about the positional operator can be found here.
Haha... you're absolutely right. I wasn't thinking clearly about how the positional operator works.
This is going to be difficult to support in the transactions package without a substantial refactor of its inner workings, so no promises about this. I do have plans to improve support for mongo operators, but this is one of the trickier ones.
I appreciate the time you put into investigating this issue so thoroughly.
No problem.
As I said before, I think that it's a good enhacement for this package, but I have no idea of how to implement it actually.
. So just feel free to tag it as an enhancement issue for the future. :P
But I'm yet find strange the inverse of the operation created. It worth a look. :)
Yes, I'll certainly take a look at that weird inverse. I really need to write a bunch more tests for this package -- coverage is spotty at best ...
Hi has there been any solution for this? Is there a way to mimic the positional operator until support for it is added?
No, there hasn't. Sorry. At the moment, what I'd do is retrieve the array, manipulate it in app code (probably using underscore or lodash), then overwrite the whole array with an update
using the $set
operator. Not cool, I know.
@fjorgemota is right, this would be a good enhancement for the package and is kind of a glaring omission at the moment.
That said, with a 3 day old baby, I'm not sure I'm going to have time to make the necessary adjustments anytime soon.
@JackAdams @fjorgemota
I figured out an alternate solution that IMHO might be a bit cleaner...
I use loadash to determine the arrayIndex of the object I want to update in the array. Then I create a custom index updater object and pass it to $addToSet which adds it only if it isn't there. In example:
var array = [{key: "value"},{key: "value2"}];
var _id = an_id;
var document = Collection.findOne({_id: an_id, "array.key" : "value"});
var index = _.findIndex(document.array, {key: "value"});
var customUpdateObj = {};
//Set custom query object with an int instead of a $ which is supported by minimongo
customUpdateObj["ingredientDetails." + index + ".stores"] = e;
Collection.update({_id: an_id, "array.key" : "value"},
{
//Only add to array in object if doesnt exist. If want to insert no matter what, use $push
$addToSet: customUpdateObj
}
)
Oh nice. Yeah, that's better and would totally work. In fact, that sounds familiar -- I've got a feeling I might have done that in my code in a few places over the years.
So... no progress?
It still doesn't work for me, any update?
No, sorry. Work on this package is back-burnered for the time being. Too many other things taking priority at the moment. I've always got time to review and merge a good PR though. :-)
Hello!
I think that it's a good enhacement for this package, but I have no idea of how to implement it actually. See:
Example
Suppose you have a document in a collection
items
with the following format:Suppose you want to increment the sub-field "freq" of the first item of the
sub_items
array so it's value will be 5. In MongoDB (and in Meteor, too), you can execute:And the document will turn into something like:
That's because of the positional operator (represented as $ in the update doc), which allows MongoDB to detect the exact index of the sub-document in the array and "replace" it in the update doc, so:
Becomes, for MongoDB:
Being
0
the index of the sub-document insub_documents
in the array.Problem
Now, the problem: If I run:
In Meteor, the following log is printed:
(btw, it's strange the "inverse" command being an $unset (as the command is an $inc, it should not be a $set or $inc with negative value?) here..)
And it's have a known cause: Meteor Transactions picks just
_id
in the update query, and so MongoDB does not have a way to discover which sub-document in the array it should update.Maybe we should detect positional operators in the update doc and so allow it's properties used in query (such as
sub_items.id
, in that example) to be used in the query, too?What do you think?
Thanks. :)