Composite objectclasses: how to handle "many-to-many" data relationships?

1 view
Skip to first unread message

jdf

unread,
Mar 20, 2005, 7:43:52 AM3/20/05
to ql...@googlegroups.com
I want to use the following tables:

members groups member_group
------- ------ ------------
uid gid uid
login name gid
passwd

where a member can belong to as many groups they like, and a group can
have as many members as it likes.

I've had a pretty thorough look at
http://www.qlime.org/0.5.1/qlime_or_mapping.html#composite-objectclasses
, but it seems only to deal with one-to-many relationships. What's the
correct way to set up a QLime registry for many-to-many relationships?

Jeremy

Shalabh Chaturvedi

unread,
Mar 20, 2005, 1:57:49 PM3/20/05
to jdf, ql...@googlegroups.com
Since the basic (and only) construct in QLime is a join, complex
relationships have to built using multiple joins.

You have three tables you therefore need two joins:

1. Composite objectclass Membership created by joining member_group to
groups on gid.

2. Also join Membership to members on uid.

In this case you have only one composite objectclass (Membership) and
two simple objectclasses (Member and Group) and can use them as follows:

# given a member find all groups

m = Member.find_one(login='...')

for membership in Membership.find(user=u):
print membership.group.name

# given a group find all members

g = Group.find_one(name='...')

for membership in Membership.find(group=g):
print membership.user.login

# another way to find all groups of a member

for membership in Membership.search(filter = Membership.user.login='...'):
print membership.group.name

Regarding many-to-many, the syntax is same as one-to-many. In fact the
only thing you specify in join is that it is '-to-many'. The join
attribute of the primary objectclass does not have to be unique. Your
example is more than just many-to-many - there is a link table, so
multiple joins are required.

Another way to do exactly what you want is the following two joins:

1. Composite objectclass MemberGroup created by joining member_group to
groups on gid.

2. Composite objectclass Member created by joining members to
MemberGroup on uid.

In this case the usage might look like:

m = Member.find_one(login='...')
for link in m.member_groups:
print link.group.name

Observe m.member_groups will be a tuple of objects of type MemberGroup
(which we're not much interested in, except for getting to Group). Also
note you can create a property called 'groups' on User that allows
easier usage.

In the future QLime might even include a feature allowing you to say
that 'a.x is the same as a.b.c.d' since using just joins you tend to
have these long attribute accesses.

Also observe that QLime does not handle the link-table as a special
case, however the basic construct of join can be used for it and
(hopefully) also for *any* kind of special cases you might have.

Here are the two ways to do it shown pictorially:

1. Membership ---> Group
|
+---------> User

2. Member --> MemberGroup --> Group

You start from the leaves and build the joins as you move up, *one join
at a time*. Based on your usage you may pick one or the other, or even a
third:

3. Group --> MemberGroup --> Member

You can look at tests/rdbtest.py (TestComposite) for a model built from
5 related tables. However it uses code (and not the config file) to
construct objectclasses.

Hopefully I made some things clearer. Btw, is this just an example or
you actually have tables and are trying to use QLime OR mapping?

Cheers,
Shalabh

Shalabh Chaturvedi

unread,
Mar 20, 2005, 2:02:27 PM3/20/05
to ql...@googlegroups.com, jdf
Correcting typos:

Shalabh Chaturvedi wrote:
> In this case you have only one composite objectclass (Membership) and
> two simple objectclasses (Member and Group) and can use them as follows:
>
> # given a member find all groups
>
> m = Member.find_one(login='...')
>
> for membership in Membership.find(user=u):
> print membership.group.name


Should be (user=m) not (user=u).

shalabh

unread,
Mar 20, 2005, 2:16:15 PM3/20/05
to ql...@googlegroups.com
Shalabh Chaturvedi wrote:

> Regarding many-to-many, the syntax is same as one-to-many. In fact
the only thing you specify in join is that it is '-to-many'. The join
attribute of the primary objectclass does not have to be unique. Your
example is more than just many-to-many - there is a link table, so
multiple joins are required.

Hmm... I created some confusion above, please ignore everything after
the first sentence :). I suppose the real answer to your question is -
you create a many-to-many join by creating two one-to-many joins. And
your example is correct - a many-to-many join does require a link table
(wonder what I was thinking!?). However everything else in my reply is
good :)

Shalabh

Reply all
Reply to author
Forward
0 new messages