Hello again. Thanks for your suggestion.

Den 03. jan. 2012 00:38, skrev Kevin R. Coombes:
Your last few posts have confused me as to the actual requirements. Suppose I have the following tree, where the numbers on the nodes are arbitrary IDs that i have assigned.
                     [1]
                      |
                 -----------
                 |         |
                [2]       [3]
                 |         |
    -----------------   ---------
    |        |      |   |       |
   [4]      [X]    [5] [6]     [7]


But if I want to insert a branch between 2 and 3 and still keep it ordered? Wouldn't I then have to give a new path to 3, 6 and 7? One solution that has been suggested is to use decimal values, so that I could do 2+3/2 to get 2.5 and use that as its path. Then, if I wanted to add a node between 2.5 and 3, I would do 2.5+3/2=2,75 and the tree would look like this:

                                [1]
                                 |
                        --------------------------------
                        |        |            |              |
                       [2]    [2,5]      [2,75]      [3]

The paths for 2 and 3, including all their child nodes would stay the same. If there are more siblings on that level, then they would also be intact with no change. However, this would be limited because there's a finite number of decimals. And there is another problem. If I now want to move 2.75 before 2.5, then I would do 2+2,5/2=2.25. The first level below the root would now be [2, 2.25, 2.5, 3], but since 2.75 is now called 2.25, I would also need to update the paths of all nodes under it. This would also mean that the tree would be in an inconsistent state between updating 2.75 itself and the updates to its child nodes. If there is a large number of elements, then this can take a considerable amount of time.

So, the current idea (that I got from Lena Herrman) is that each element only points to its direct parent and to its next sibling. That way, any operation would only require two writes, regardless of the size of the tree:

                                [1]
                                  |
                        -----------------------------
                        |                                 |
                      [2]                              [3]
                        |                                 |
                ---------------                ------------
                |              |                  |             |
               [4]          [5]               [6]          [7]

(Yes, same tree, just repeated for your convenience:))

In this case, the JSON would look something like:
{"_id" : "uuid1", "label" : "1", "parent" : null, "next_sibling" : null, "root_node" : true } {"_id" : "uuid2", "label" : "2", "parent" : "uuid1", "next_sibling" : "uuid3", "first_child" : true }
{"_id" : "uuid3", "label" : "3", "parent" : "uuid1", "next_sibling" : null }
{"_id" : "uuid4", "label" : "4", "parent" : "uuid2", "next_sibling" : "uuid5", "first_child" :true }
{"_id" : "uuid5", "label" : "5", "parent" : "uuid2", "next_sibling" : null }
{"_id" : "uuid6", "label" : "6", "parent" : "uuid3", "next_sibling" : "uuid7", "first_child" : true }
{"_id" : "uuid7", "label" : "7", "parent" : "uuid3", "next_sibling" : null }

So now, if I wanted to move 2 to 7, then I would do

{"_id" : "uuid2", "label" : "2", "parent" : "uuid7", "next_sibling" : null, "first_child" : true } {"_id" : "uuid3", "label" : "3", "parent" : "uuid1", "next_sibling": null, "first_child": true }

If, instead, I wanted to move 5 before 4, then I would do

{"_id" : "uuid5", "label" : "5", "parent" : "uuid2", "next_sibling" : "uuid4", "first_child" : true } {"_id" : "uuid4", "label" : "4", "parent" : "uuid2", "next_sibling": null, "first_child": false }

No other writes would be necessary, no matter what you do, or how large the changes are. There are also no problems with decimals. You can reorder the tree how many times you want. That is a huge improvement, but it would still mean that the tree is broken between the first write and the second. I think I can do this by adding a field that signifies that the first is the beginning of an operation and that the second write finishes it.

The problem is how to get the tree in an ordered state from the database. I currently sort by root_node, then parent, then first_child. This means I can always get the starting points quickly, but I'll have to rebuild the tree on the client. It's not really a big problem, but if I use the tree in one Python desktop app and one JavaScript browser app, then I'll have to do that work twice. I would much rather do it on the server so I could just loop through on the client. That would also reduce the amount of work that is necessary.

It feels like there should be a better way to do it, but I can't really get it to the front of my mind. :)


Jo-Erlend

Reply via email to