janez89 / mongoose-materialized

mongoose materialized plugin
59 stars 22 forks source link

save dynamically deep document #8

Open DJWassink opened 10 years ago

DJWassink commented 10 years ago

I wan't to dynamically update a document (so I don't know which key/values get passed to the save function). And the key/values can be nested prety deep, Once again you don't know how deep.

Currently I do this by first getting the document from the database and extend it with the data passed to the update. However this way the document also get converted to a plain object (toObject()).

Big downside of this is that we can't use the .save() method any more because it has become a plain object. Big no no of this story is that the parentId is (maybe) updated in the progress but the path doesn't get updated.

Is there some way to dynamically update a deep nested document while also updating the materialized path?

Maybe it's a idea to also make a method which will only update a specific document its path (or starting from that document it's path and recursively do all it's children), much like the .Building does now but only from the updated document it's id.

Note: to explain it a bit more, this is what is basically wanna do but in less functions (somehow this doesn't work though. The parentId does get updated but the path doesn't)

node = extend(true, node.toObject(), data);

Node.findByIdAndUpdate(data._id, node, function(err, doc) {
    Node.findById(doc._id, function(err, savedNode) {
        console.log(savedNode.parentId);
        savedNode.setParent(savedNode.parentId);
        savedNode.save(callback);
    });
});
janez89 commented 10 years ago

I put in a setting that uses the toObject was in the tree.

I see a lot of functions would be needed. The sub-tree traversal and updates.

The 2.0 version is a closer look through and think about it. OPEN is an issue https://github.com/janez89/mongoose-materialized/issues/9 where I'm waiting for ideas, missing features.

janez89 commented 10 years ago

Just a thought.

Save the document a problem, because: { "_id": "...", "parentId": "...", "path": "...", "children": [ ...] }

The mongoose is trying to save the children attribute. The documents have been specially converted to object because it violates the schema. We need to decouple think that we want to display the data or operation is to be done with it. With this in mind I'm trying to plan the 2.0 version.

DJWassink commented 10 years ago

Hmm interesting, but you completely misunderstood my ticket (I am terrible at explaining what I think especially in English). But with your 2 answers I am able to explain it a bit more and directly see that I am also doing wrong stuff with Mongoose.

Basically I want to save a document which is dynamically (so you don't know which properties it has just that it is a valid object). To save something like this through mongoose I have the schema strict option set ot false. This so that I can also save properties which aren't defined in the Schema.

This however isn't possible with the materialized plugin because we only have a document.save() method. So basically if we did have a

Model.update( <CONDITION> , <FIELDS> )

method it would be possible to dynamically modify fields inside a unknown document. And ofcourse it would be super awesome if we could integrate it with some operators but I guess that is going to far and will be to dangerous since you are more likely to add operators that will eventually break the tree.

Anyhow a findByIdAndUpdate sort of function would be ideal!

janez89 commented 10 years ago

Sorry my English is not so good.

Sorry, I think I missed one of two details. I described the .save() method apply to the tree.

I think during the valid that the children attribute with strict option is not defined. Yes if turn off strict option, then you can save this. But this is not supposed, because reserved for toTree() method. if you use the .save() method inside of result tree, without strict:true option you save the children to collection. In turn will lead to problems. This the reason to use toObject() method was.

If you want update the document inside of tree, you can retrieve it again from db, and update fields with .save() method.

Unfortunately, the findByIdAndUpdate not triggered Mongoose event hooks: pre('save'), etc... Therefore the paths not changed. Only you can use .save() method.

I called this to the attention. In "important" section the method list: https://github.com/janez89/mongoose-materialized#instructions

I see one more chance. Making a saving for special method which omits the children were saved. If you use save method and exists children, than skip the children attribute. I will try to do today.