[ZODB-Dev] Re: Ruby/Smalltalk OODB

Sean Allen sean at monkeysnatchbanana.com
Tue Jun 3 15:44:01 EDT 2008


On Jun 3, 2008, at 1:13 PM, Gary Poster wrote:

> Uh-oh, I'm implicated!
>
> (see below)
>
> On Jun 3, 2008, at 12:53 PM, Sean Allen wrote:
>>>
>
> ...
>
>>>
>>>> If you do that in gemstone, there is only one copy of Order B, no  
>>>> matter
>>>> what variable in what dictionary you come at it from. And its  
>>>> drop dead
>>>> simple.
>>>
>>>> I looked at implementing that with zodb and moved along.
>>>
>>> I'm confused. This has been the way the ZODB worked for a long time,
>>> unless I'm really missing something in your description.
>>
>> i tried to do this:
>>
>> create customer that has order
>>
>> so that i can have different extents type situations...
>>
>> store customer in one dictionary.
>> store order in another.
>>
>> if i pulled the order back out from the order dictionary and  
>> modified it
>> then pulled the customer out, the customers order was no longer in  
>> sync
>> with what came out of the order dictionary.
>>
>> the reference was lost on serialization. original in memory objects  
>> were fine,
>> those that came back out from zodb werent.
>>
>> i'm going to quote the initial email i sent with the idea in  
>> general and the followup i got
>> and i then tried it out to make sure i hadnt asked the question  
>> wrong, and yeah...
>> what i wanted to do, wasnt easily done.
>>
>> the quotes:
>>
>>> The biggest concern I have is how do to the layout/storage so that  
>>> this slightly contrived example works:
>>>
>>> Product has a brand.
>>> There are many brands.
>>>
>>> How do I store so that I can find all products simply and all  
>>> brands simply and also so that changes in a brand instance are  
>>> reflected when
>>> the product instance is deserialized. By 'simply' I mean that it  
>>> doesnt really work on our end to have to walk all Products looking
>>> for unique brands. Should just be able to go directly in and get  
>>> said brands ( using keys() or similar call ).
>>>
>>> If I create 'brand' and 'product' as btrees, then if i do  
>>> something like
>>>
>>> some_product.brand.name = 'something entirely different'
>>>
>>> and that brand already exists in 'brand', would it be updated? are  
>>> references maintained in that fashion?
>>> do we have to handle manually on update and creation?
>>>
>>> Note that we would just be using ZODB not Zope in this scenario.
>>
>> Back references are not maintained automatically.
>>
>> I'd identify two classic solutions to this sort of thing.
>>
>> One is to make a custom mapping (using a BTree as the inner data  
>> structure) that maintains back-references when objects are placed  
>> in them or removed.  zope.app(.container? .folder? I'd have to  
>> look) has code that does this, along with firing events.  For  
>> simple stories like the one you describe here, that's what I'd  
>> probably recommend.  It works to the strengths of the ZODB, which  
>> particularly shines in terms of readability when you just need to  
>> walk a tree of attributes to get what you want.
>>
>> The other is to keep an external index, a la zc.extrinsicreference  
>> or zc.relation.
>>
>> zc.extrinsicreference does not have too many dependencies beyond  
>> ZODB, and as long as zope.app.keyreference doesn't drag much along  
>> with it, might be usable as a library.  That said, it's also very  
>> simple, and could be used as a model for you, even if you don't use  
>> it directly.  It would also be a reasonable choice for a simple  
>> situation like the one you describe.  It relies on events to update  
>> its data structures.
>>
>> zc.relation an almost-released-revision of zc.relationship that  
>> drastically reduces dependencies--actually, it has no additional  
>> dependencies to ZODB, as you can see at http://svn.zope.org/zc.relation/trunk/setup.py?view=markup 
>> .  It's also a bit overwhelming and low-level: see the README:http://svn.zope.org/zc.relation/trunk/src/zc/relation/README.txt?view=auto 
>>  .  It doesn't hook anything up for you: you set the relationship  
>> catalog up and you arrange for it to be updated, via events or  
>> direct messages.  That said, if you need its power, it is well- 
>> tested and would be a good choice for some jobs from at least some  
>> perspectives (caveat read-or: I'm the author).
>
> Now in the context of this discussion, I see that I misread you.  I  
> apologize.
>
> This works out of the box:
>
> You have a Product class and a Brand class.  Both inherit from  
> persistent.Persistent.
>
> You have a persistent-aware mapping such as a BTree.
>
> In the root of your ZODB, put two BTrees, one for your products and  
> one for your brands.
>
> Create some Brand instances and put them in the brand mapping.
>
> Create some Product instances and put them in the product mapping.   
> Assign some of the brands you have made as attributes of the products.
>
> Now, product.brand.foo = 'bar' (in any thread or any ZEO client)  
> will be changing the same effective object (let's call it a record)  
> as the one in the brand mapping you have in the root of your db.
>
> I believe that this is what you are talking about.
>
> Again, I apologize for not reading your original question closely  
> enough.
>
> What you *can't* do out of the box is ask "hey, what products have  
> an attribute that points to this brand?".  That's a back-reference,  
> and that needs solutions like the ones to which I was referring.
>
> Gary

That means when I tested it, I did something horribly wrong in my code.
Damn.
I'm going to have to dig my test code up and see what I really screwed  
up.




More information about the ZODB-Dev mailing list