We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev. http://www.zope.org/Members/upfront/ZODBRelationships Your comments would be appreciated. Shane, thanks for all your help! -- Roché Compaan Upfront Systems http://www.upfrontsystems.co.za
At 11:07 PM 5/8/03 +0200, roche@upfrontsystems.co.za wrote:
We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev.
http://www.zope.org/Members/upfront/ZODBRelationships
Your comments would be appreciated.
Issues: 1. "Global relationship repository" has no use cases, and smells like trouble. Why not just explicitly store the Relationship() somewhere? After all, every RelationshipView will have a reference to it. (For ZODB4, a persistent module might be the natural place to put the "official" reference to the Relationship(); for ZODB3, just hang them off the root with suitably unique keys.) 2. There is no directionality to the associations; this doesn't work for hierarchies or graphs. E.g. think 'parent_child = Relationship()'. That won't work. All in all, I don't see any reason to make this part of ZODB's API or add special repositories to support it. However, like PersistentDict or BTree, relationships might be a nice tool to have available in the ZODB library. A final comment... Once this takes directionality into consideration, you might consider calling it an 'Association' rather than a 'Relationship', as it would then largely meet the MOF and UML semantics of an "Association". That is, an association is a collection of directed links between objects. It would then make sense to refer to refer to the 'RelationshipView' as an 'AssociationEnd'.
Phillip J. Eby wrote:
At 11:07 PM 5/8/03 +0200, roche@upfrontsystems.co.za wrote:
We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev.
http://www.zope.org/Members/upfront/ZODBRelationships
Your comments would be appreciated.
Issues:
1. "Global relationship repository" has no use cases, and smells like trouble. Why not just explicitly store the Relationship() somewhere? After all, every RelationshipView will have a reference to it. (For ZODB4, a persistent module might be the natural place to put the "official" reference to the Relationship(); for ZODB3, just hang them off the root with suitably unique keys.)
First, I also think it should be possible to have more than one relationship. On argument for that is complexity of searches, another is virtual hosting and managability (import/export). Additionaly, why should relationship repositories just hang down the root and have unique ids? Maybe this is Zope3 related (which I don't know much about), but in zope2, it might be nice to use the acquisition machinery in discovering relationship storages. Example: You want to create amazon2. Your products are stored in a folder hierachy. books science philosopy mathematics CS OO Python Zope Twisted ... Java Websphere ... C++ C# Producural C ... ... etc. You want to implement something like "People who were interested in <spam> also were interested in <eggs>" - but on every level of the hierachy, i.e. (Zope, Twisted) in the deepest, one above (Python, Java) etc. Now, wouldn't the most natural and economic way to do that to put a RelationshipStorage in every level? Even if we consider the case that we'd like to store Relationships crossing hierachies, e.g. (Zope,Websphere), they'd be stored in the Relationship Storage which an ancestor of both of the objects to be stored, i.e. the one lying under OO. cheers, oliver
First, I also think it should be possible to have more than one relationship.
You can have as many relationships as you like .. (ah, I see you miss-spoke :] ). Yes, you should be able to have multiple relationship repositories. The proposal doesn't address that now.
On argument for that is complexity of searches, another is virtual hosting and managability (import/export).
Makes sense ..
Additionaly, why should relationship repositories just hang down the root and have unique ids?
Maybe that can be rephrased as "the root of the app", and the proposal revised .. -- Jean Jordaan http://www.upfrontsystems.co.za
On Thu, 08 May 2003 19:58:22 -0400 "Phillip J. Eby" <pje@telecommunity.com> wrote:
At 11:07 PM 5/8/03 +0200, roche@upfrontsystems.co.za wrote:
We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev.
http://www.zope.org/Members/upfront/ZODBRelationships
Your comments would be appreciated.
Issues:
1. "Global relationship repository" has no use cases, and smells like trouble. Why not just explicitly store the Relationship() somewhere? After all, every RelationshipView will have a reference to it. (For ZODB4, a persistent module might be the natural place to put the "official" reference to the Relationship(); for ZODB3, just hang them off the root with suitably unique keys.)
2. There is no directionality to the associations; this doesn't work for hierarchies or graphs. E.g. think 'parent_child = Relationship()'. That won't work.
What we have at the moment is a graph and strictly speaking a graph has no direction in its edges (maybe you meant directed graph). As far as I can see graphs are possible, hierarchies are not. Can't one just use containment to represent hierarchies? If one can what other use cases are there for directionality in associations?
All in all, I don't see any reason to make this part of ZODB's API or add special repositories to support it. However, like PersistentDict or BTree, relationships might be a nice tool to have available in the ZODB library.
A final comment... Once this takes directionality into consideration, you might consider calling it an 'Association' rather than a 'Relationship', as it would then largely meet the MOF and UML semantics of an "Association". That is, an association is a collection of directed links between objects. It would then make sense to refer to refer to the 'RelationshipView' as an 'AssociationEnd'.
We used the term Relationship because the proposal is based on the entity-relationship model. I am not too familiar with MOF so maybe you can explain how it will apply to the current proposal. Thanks for your comments Phillip. I was hoping you say something because you must have thought about this when designing PEAK. -- Roché Compaan Upfront Systems http://www.upfrontsystems.co.za
On Fri, 2003-05-09 at 05:28, Roché Compaan wrote:
On Thu, 08 May 2003 19:58:22 -0400 "Phillip J. Eby" <pje@telecommunity.com> wrote:
At 11:07 PM 5/8/03 +0200, roche@upfrontsystems.co.za wrote:
We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev.
http://www.zope.org/Members/upfront/ZODBRelationships
Your comments would be appreciated.
Issues:
1. "Global relationship repository" has no use cases, and smells like trouble. Why not just explicitly store the Relationship() somewhere? After all, every RelationshipView will have a reference to it. (For ZODB4, a persistent module might be the natural place to put the "official" reference to the Relationship(); for ZODB3, just hang them off the root with suitably unique keys.)
2. There is no directionality to the associations; this doesn't work for hierarchies or graphs. E.g. think 'parent_child = Relationship()'. That won't work.
What we have at the moment is a graph and strictly speaking a graph has no direction in its edges (maybe you meant directed graph). As far as I can see graphs are possible, hierarchies are not. Can't one just use containment to represent hierarchies? If one can what other use cases are there for directionality in associations?
Dependency: - Object 'foo' dependsd on object 'bar'. Asymmetric business associations - Jane is the boss of Fred. - Invoice line items decrement the stock count of SKU items. etc. I would argue that symmetric (undirected) graphs are much less common in business applications than asymmetric ones.
All in all, I don't see any reason to make this part of ZODB's API or add special repositories to support it. However, like PersistentDict or BTree, relationships might be a nice tool to have available in the ZODB library.
+1 to that. I guess I can't figure out what the ZODB has to do with relationships.
A final comment... Once this takes directionality into consideration, you might consider calling it an 'Association' rather than a 'Relationship', as it would then largely meet the MOF and UML semantics of an "Association". That is, an association is a collection of directed links between objects. It would then make sense to refer to refer to the 'RelationshipView' as an 'AssociationEnd'.
We used the term Relationship because the proposal is based on the entity-relationship model. I am not too familiar with MOF so maybe you can explain how it will apply to the current proposal. Thanks for your comments Phillip. I was hoping you say something because you must have thought about this when designing PEAK.
E-R models derive largely from the RDBMS world; UML class models are not completely isomorphic with them, but might be a better fit for the kind of thing you are thinking about (for instance, E-R models generated from class models often show weird "extra" tables to capture the oddities of mxn relationships). Tres. -- =============================================================== Tres Seaver tseaver@zope.com Zope Corporation "Zope Dealers" http://www.zope.com
Ugh, which mailing list should I send this to? I'm going to pick zope-dev since it's a fairly general list without too much traffic. Phillip J. Eby wrote:
Issues:
1. "Global relationship repository" has no use cases, and smells like trouble. Why not just explicitly store the Relationship() somewhere? After all, every RelationshipView will have a reference to it. (For ZODB4, a persistent module might be the natural place to put the "official" reference to the Relationship(); for ZODB3, just hang them off the root with suitably unique keys.)
One thing that perhaps wasn't made clear is that the repository doesn't directly contain relationships. It contains named relationship sets. I don't know if this is what you're talking about--correct me if I misunderstood.
2. There is no directionality to the associations; this doesn't work for hierarchies or graphs. E.g. think 'parent_child = Relationship()'. That won't work.
I have that concern also, although it was only a gut feeling until now. Elaborating on your example, an object may participate in multiple parent/child relationships, sometimes as a parent, sometimes as a child. With the current API, you can't distinguish between the parents and the children. That certainly won't work, and I'm sure it's only one example of needing directionality.
All in all, I don't see any reason to make this part of ZODB's API or add special repositories to support it. However, like PersistentDict or BTree, relationships might be a nice tool to have available in the ZODB library.
That is what is intended by the proposal. Jim suggested, in fact, that all this might be used independently of ZODB.
A final comment... Once this takes directionality into consideration, you might consider calling it an 'Association' rather than a 'Relationship', as it would then largely meet the MOF and UML semantics of an "Association". That is, an association is a collection of directed links between objects. It would then make sense to refer to refer to the 'RelationshipView' as an 'AssociationEnd'.
That is an excellent idea if we can determine that this project is distinct from the Zope 3 relationship service. It feels like the two projects are aiming to solve largely the same problem, but if they aren't, a name change will help clarify the difference. Shane
roche@upfrontsystems.co.za wrote:
Very interesting. What I miss is a way to name the relationship so you can specify which relationship you are interested in. That just fuzzily specify that object A has some sort of relationship to object B doesn't seem very useful... The typical use of a relationship storage is to ask the relationship repository for all students for a course. But if the relationship is only stored as 'there is a relationship', then all teachers would pop up to. The RelationshipViews partially solve this, but require you to load the objects, and therefore you might still need to traverse the ZODB to find all the objects you are gonna query. I have missed this type of functionality, but I always saw it as an extention to the Catalog, so that you could query not only on indexesd metadata, but also on relationships to other objects. It would of course be possible to add functionality to the Catalog to query this even if the relationships are not stored in the Catalog itself. In any case, the relationship would need an id so you can specify which relationship you want to query.
Very interesting. What I miss is a way to name the relationship so you can specify which relationship you are interested in.
Isn't this naming the relationship? student_courses = Relationship() So you can examine the relationship you are interested in by finding it in the repository for relationships (eg. in a folder) as: <relationshipfolder>.student_courses <relationshipfolder>.course_teachers
to. The RelationshipViews partially solve this, but require you to load
pete.courses and student_courses.get(pete) are different ways of saying the same thing. If you set a RelationshipView on an object, you can use both ways, but the first way is the shortest and most pythonic. For 3rd party objects that are ignorant of relationships, you must use the second way.
I have missed this type of functionality, but I always saw it as an extention to the Catalog, so that you could query not only on indexesd metadata, but also on relationships to other objects.
It is akin to the Catalog, but the proposal aims to provide relationships in the absence of Zope and the Catalog as well. Also, relationships are bidirectional, which a Catalog is not. -- Jean Jordaan http://www.upfrontsystems.co.za
Jean Jordaan wrote:
Isn't this naming the relationship?
student_courses = Relationship()
So you can examine the relationship you are interested in by finding it in the repository for relationships (eg. in a folder) as:
<relationshipfolder>.student_courses <relationshipfolder>.course_teachers
Well, the above code doesn't create that attribute... It would have to be: <relationshipfolder>.student_courses = Relationship() And that kills off the idea of a global storage (which I don't mind at all. I don't really see the use of having several relationship storages, but I'm easily convinced otherwise if somebody can come up with a good use case). The above code also is bad because it allows anybody to kill all stored relations by just creating a new Relations object and assigning that to the object attribute. It's then better to have an API more like <storage>.addRelation(relid, objecta, objectb) The relationship with id relid would then be created if it didn't exist. Or you could create the relationship separately, but still by using a method call that check that it doesn't overwrite and kills an existing relationship. Like addIndex() on a catalog. This would mean that you have code more like this: class course: def __init__(self): relstorage = GetRelationshipStorage() relstorage.CreateRelationship('students') def assignStudent(self, student): relstorage = GetRelationshipStorage() relstorage.addRelationship('students', self, student) That last part could also be: relstorage.students.addRelationship(self, student) but I don't like that, really. I could go for relstorage['students'].addRelationship(self, student) though.
student_courses = Relationship()
So you can examine the relationship you are interested in by finding it in the repository for relationships (eg. in a folder) as:
<relationshipfolder>.student_courses <relationshipfolder>.course_teachers
Well, the above code doesn't create that attribute...
Indeed, written out properly it would be something like: student_courses = Relationship() <relationshipfolder>._setObject('student_courses', student_courses)
The above code also is bad because it allows anybody to kill all stored relations by just creating a new Relations object and assigning that to the object attribute.
Then don't do that ..
It's then better to have an API more like
<storage>.addRelation(relid, objecta, objectb)
You could still delete the storage if you wanted to kill all stored relations, couldn't you?
class course: def __init__(self): relstorage = GetRelationshipStorage() relstorage.CreateRelationship('students')
def assignStudent(self, student): relstorage = GetRelationshipStorage() relstorage.addRelationship('students', self, student)
According to the proposal, you first create a relationship, and then you add a view of that relationship (either a ComputedAttribute or a descriptor) to your class, if you want to access the relationship as an attribute on your class. If the relationship repository is not global, the view would have to acquire it. -- Jean Jordaan http://www.upfrontsystems.co.za
Lennart Regebro wrote:
roche@upfrontsystems.co.za wrote:
Very interesting. What I miss is a way to name the relationship so you can specify which relationship you are interested in. That just fuzzily specify that object A has some sort of relationship to object B doesn't seem very useful...
The typical use of a relationship storage is to ask the relationship repository for all students for a course. But if the relationship is only stored as 'there is a relationship', then all teachers would pop up to.
When using mxmRelations you have a folder called "relations" in this folder you put different instances of the mxmRelations class. So you would in effect have: relations/ students_classes teachers_classes Then you would find the students by: context.relations.students_classes.get(some_course) which will then return a list of all students. regards Max M
Lennart Regebro wrote:
roche@upfrontsystems.co.za wrote:
Very interesting. What I miss is a way to name the relationship so you can specify which relationship you are interested in. That just fuzzily specify that object A has some sort of relationship to object B doesn't seem very useful...
The typical use of a relationship storage is to ask the relationship repository for all students for a course. But if the relationship is only stored as 'there is a relationship', then all teachers would pop up to.
When using mxmRelations you have a folder called "relations" in this folder you put different instances of the mxmRelations class. So you would in effect have: relations/ students_classes teachers_classes Then you would find the students by: context.relations.students_classes.get(some_course) which will then return a list of all students. regards Max M
Lennart Regebro wrote:
roche@upfrontsystems.co.za wrote:
Very interesting. What I miss is a way to name the relationship so you can specify which relationship you are interested in. That just fuzzily specify that object A has some sort of relationship to object B doesn't seem very useful...
The typical use of a relationship storage is to ask the relationship repository for all students for a course. But if the relationship is only stored as 'there is a relationship', then all teachers would pop up to.
When using mxmRelations you have a folder called "relations" in this folder you put different instances of the mxmRelations class. So you would in effect have: relations/ students_classes teachers_classes Then you would find the students by: context.relations.students_classes.get(some_course) which will then return a list of all students. regards Max M
roche@upfrontsystems.co.za wrote:
We finally have a proposal out for ZODB relationships. This proposal presents an API for relationships, summarises ideas and contributions from a lot of people and was fuelled by the recent discussions about relationships on Zope3-dev and Zope-dev.
http://www.zope.org/Members/upfront/ZODBRelationships
Your comments would be appreciated.
I have found the need for an API change. This: def get(obj): """ Returns all objects related to this object as a set, or an empty set. """ Should really be changed to; def get(objects): """ Returns all objects related to these object as a set, or an empty set. """ Frequently I need to get an aggregated list of relations. Ie. if I want to find all the student in a "department" I first find all the courses in that department, and then I find all the unique students. For things like that I have found that I very often use this idiom: unique = {} for obj in objects: result = self.relations.students_class.get(obj) for r in result: unique[tuple(r.getPhysicalPath())] = r aggregated = unique.items() It would be much easier to be able to pass a sequence and just use: aggregated = self.relations.students_class.get(objects) It is also consistent with the use of list and objects as passed to relate etc. regards Max M
participants (9)
-
Jean Jordaan -
Lennart Regebro -
Max M -
Oliver Bleutgen -
Phillip J. Eby -
roche@upfrontsystems.co.za -
Roché Compaan -
Shane Hathaway -
Tres Seaver