mongodb-js / jsonpatch-to-mongodb

Convert JSON patches into a MongoDB update
MIT License
35 stars 27 forks source link

jasonpatch add is not interpreted correctly #6

Closed euan-smith closed 7 years ago

euan-smith commented 8 years ago

At the moment you interpret op:"add" as $push, however add is used for plain properties as well as arrays, and for the cases where $push is the correct method the path needs to change.

for example:

if the input object is {name:"alice", children: ["bob","charlie"]}

[op: "add", path: "/spouse", value: "dave"] is equivalent to {$set: {spouse: "dave"}} [op: "add", path: "/children/1", value: "eve"] is equivalent to {$push: {children: {$each: ["eve"], $position:1}}} [op: "add", path: "/children/-", value: "eve"] is equivalent to {$push: {children: "eve"}}

see here and here

martinbutt commented 8 years ago

Does anyone have thoughts on how this could be solved. It seems right now you would have to query the data to find out if you should use $set or $push.

tellnes commented 8 years ago

You could document that integers and - is expected to be an array and everything else is expected to be a property.

euan-smith commented 8 years ago

@tellnes that is exactly what I ended up doing for the project I'm currently working on, but in this case I'm also in full control of the form of the documents so I can ensure that this is always a valid assumption. Without knowledge of the data I can't see what else could be done as there just isn't enough information.

kyv commented 8 years ago

Maybe not the best solution but this seems to work ok:

6,11c6,18 < if(!update.$push) update.$push = {}; < if(!update.$push[path]) { < update.$push[path] = p.value; < } else if (update.$push[path]) { < if(!update.$push[path].$each) { < update.$push[path] = {$each : [update.$push[path]]};

>       if (path.split('.').length < 2){
>         if(!update.$set) update.$set = {};
>         update.$set[toDot(p.path)] = p.value;
>       }
>       if(path.split('.').length > 1){
>         if(!update.$push) update.$push = {};
>         if(!update.$push[path]) {
>           update.$push[path] = p.value;
>         } else if (update.$push[path]) {
>           if(!update.$push[path].$each) {
>             update.$push[path] = {$each : [update.$push[path]]};
>           }
>           update.$push[path].$each.push(p.value);
13d19
<         update.$push[path].$each.push(p.value);
sclausen commented 8 years ago

@kyv could you create a pull-request for this?

imlucas commented 7 years ago

Believe this is now fixed w #7 shipping in 0.4.0. Please feel free to reopen though.

kevinfairclough commented 7 years ago

This doesn't seem to work getting mongo patches being created like so

{ '$push': { 'ArrayName.-': 'some value' } }

It is retaining the '.-' append character and failing with mongo error 16837