Helmut Merz wrote:
>there are quite a few solutions out there in the Zope world that
>allow the management of relations or references between objects.
>So I have been working with the reference engine provided by
>Archetypes (as part of Plone) for nearly two years now; and I
>also had a look at some proposals on zope.org and
>implementations that are available in the Zope 3 packages from
>SchoolTool and CPSSkins.
>I have to confess that I was not really happy with any of these
>proposals or solutions - a feeling that we may discuss in more
>detail, the main point being just that I wanted to have
>something simple that is nevertheless flexible enough to
>accommodate to various needs.
>So I came up with the following stuff (mainly combining concepts
>by Jean-Marc Orliaguet and implementation ideas from Archetypes
>A relation is an object providing the IRelation interface. This
>has got two attributes ('first', 'second' - dyadic relation) or
>three ('first', 'second', 'third' - triadic relation). (You may
>ignore triadic relations if you don't think you need them.)
>If I now create corresponding classes (DyadicRelation,
>TriadicRelation) I can assign the objects taking part in a
>relation directly to these attributes of the relation. (Note
>that the objects taking part in a relation are not touched at
>all.) In fact I create a class for each kind of relation (each
>relationship or predicate or whatever you like to call it)
>I want to use.
>So the question arises what to do with the relation objects? The
>point here is not so much where to store them but how to make
>sure that we can find them. So we need a registry for relations
>- interface IRelationsRegistry.
>This has three methods:
>The keyword arguments to the query() method may be:
>- relationship=... - a relation class (we can also work with
> named predicates - see below)
>- first=... - an object
>- second=... - an object
>- third=... - an object
>One can combine those arguments at will to search for all
>relations of the relation class specified (if given) with the
>given values for the attributes. The list may be extended if you
>use relation classes with additional attributes you want to
>(For details have a look at the README.txt and other files on
>or check it out via
>svn co svn://svn.cy55.de/Zope3/src/cybertools/trunk/relation)
>You see that this looks very much like a catalog search - so why
>not implement the relations registry as a subclass of
>OK, so the RelationsRegistry class is derived from Catalog, and
>of course it is a local utility. The indexes are just FieldIndex
>objects, using an adapter to provide unique ids for the objects
>involved via the IntIds utility; the same is done for providing
>ids for the relation objects themselves. The relationship is
>mapped to the full module path + class name of the relation
>An interesting consequence of this is that the relation objects
>are not explicitly stored somewhere, the only reference to them
>is via the IntIds utility. Thus you are free to store them in
>some container or even make them first class content objects if
>you want - but you needn't.
>The whole stuff is flexible enough to be extended as needed, e.g.
>with special registry classes used via named utilities,
>additional attributes on relations (easily indexable in the
>registry); it could be wrapped in a richer and more
>application-oriented API, etc.
>It is also possible to use named predicates (with URIs or strings
>like '_ is child of _') instead of different relation classes to
>represent relationships (this is shown by an example at the end
>of the README.txt).
>So what do you think? - any feedback and suggestions welcome...
>I'd also gladly write a proposal (if I get write access to the
>wiki ;-)) and of course change the license from GPL to ZPL if
>this would be considered useful.
I can tell you about the design decisions made in the case of the
relation tool included in CPSSkins. They don't necessarily appear in the
code itself in an obvious way.
1) separate storage from storage policy
the relation storage stores what it is told to store, as long as the
objects are Relatable they can be stored. The storage policy (using
unique ids or not, etc..) is the responsibility of the application
itself. To impose a unique id policy when storing elements would be a
mistake in my opinion (in the case of cpsskins it wouln't work either).
2) keep the relation storage index as small as possible.
Do not index predicates, the same predicates are used in too many
relations, the size of the index ould just increase dramatically.
Instead only index the elements that are inside the relation, the
chances that the same elements are related in many different ways are
I don't know about using the zc.catalog for indexing relations, you
could end up in huge indexes and very slow queries.
3) don't make the API for querying the storage be too intelligent,
to create complex queries, create complex predicates instead, i.e.
- predicates that combine several predicates
- proxy predicates (when the predicate is evaluated at runtime and a
method is specifed instead)
if you need to do really complex queries, do several queries and
filter out the results afterwards in you application unless you're fine
with ending up with a huge catalog index.
Zope3-dev mailing list