[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