Hi Ben, You have two options here, either of which would appear to suit your situation very well:
1) Use App Engine's built in support for parent entities and entity groups. When creating a node, pass the parent= argument to the constructor, passing the key or model instance of the parent node. All entities with the same root node can be updated atomically in a single transaction. To fetch all the entities of a tree, do MyEntity.all().ancestor(rootkey). 2) Encode your entire tree in a single entity - for example, by pickling it. Which of the two is better depends on a few external factors - for example, do you ever need to look up individual tree nodes by criteria other than their membership in a particular tree? -Nick Johnson On Sat, Jun 6, 2009 at 4:41 PM, Ben FS <ben.su...@gmail.com> wrote: > > Hi Nick, > I'm faced with a similar question as the original poster and can > provide additional details on the nature of the tree and operations in > my case, as you request below. I'm hoping this will make it possible > for you to help me out. > > Yes, I would like tree modifications to be wrapped in transactions. > Assuming "1QPS of updates" means "one datastore write per second", the > answer is yes, I expect write frequency for a single tree to be within > that limit. > My trees will be shallow (typically 1-4 levels deep; user-defined and > if needed I can enforce a limit). > The number of nodes in a tree will typically be <30 and rarely if ever > >100. > Occasionally an update will need to modify attribute values on > multiple nodes within a branch, and should occur within a transaction. > A given request (via AJAX) will typically read the entire tree > structure (of a single tree). There will be far more reads than > writes, and it is okay for writes to be less snappy, but I'd like > reads of the entire tree to be fast. > > Operations: > 1. Read the tree of entities: Get the whole tree. List all root nodes. > Given any node, retrieve its children. Given any node, retrieve the > entire sub-tree. Given any node, retrieve its parent. Query all nodes > based on some attributes. > 2. Write a tree of entities: Add a root node. Add a child node. Remove > a node. Removing a node that has children should have two options: a) > fail, or b) cascade (remove all generations of children). Modify > attributes on a single node. Modify attributes of a set of nodes > (usually within a branch, e.g. update ancestors bottom-up). > > I'm currently using the Java runtime with low-level datastore API, but > also use Python, and am interested in this from a general point of > view. > > A little more info, not sure if this helps: > My app has multiple projects with multiple project members each. > Within each project there are two main tree structures, G and O, each > with variable number of levels, and multiple nodes at the root level > (users see G and O as lists initially and then each item is broken > down further, developing a tree). Each node (in both G and O) has > various attributes, some of which have numerical values. Numerical > attributes of leaf nodes are modified by users; numerical attributes > of non-leaf nodes are computed from those of their children. In > addition the two trees are interrelated: each leaf node of G is linked > to each leaf node of O. For each such pairing additional attributes > exist and their values can be modified by users. > > Alternatively, you can think of two lists of items, cross-related to > form an MxN matrix, with these items forming the leaves of two tree > structures (G and O) superimposed on the lists (M leaves of G and N > leaves of O). > > I appreciate any advice you can provide! > > Thanks, > Ben. > > On Apr 28, 4:22 am, Nick Johnson <nick.john...@google.com> wrote: > > The best way to do this depends on the nature of thetree, and what > > sort of operations you need to do on it. > > > > If you need transaction support and will do less than about 1QPS of > > updates to the entiretree, you could use the datastore's built in > > Ancestor model - construct entities with the 'parent' argument to the > > constructor. This also means you can't change the parent of an > > existing entity. > > > > If the above isn't satisfactory, but your trees will be relatively > > shallow (say, typically less than 100 levels deep), you can store an > > ancestor list in a ListProperty. This way, you can select all > > descendents of a given node easily. > > > > Other options are available, of course, but they entail multiple > > operations to retrieve a whole subtree. If you give more detail as to > > what you're representing and your access patterns, I can suggest more > > alternatives. > > > > -Nick Johnson > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google App Engine" group. To post to this group, send email to google-appengine@googlegroups.com To unsubscribe from this group, send email to google-appengine+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en -~----------~----~----~----~------~----~------~--~---