i've had this sitting around in my sandbox for a while, but with the 4.8/5.0 dev cycle, I was too busy to do much with it. it's a proposed relationship API for inclusion into drupal's core.
Schema-wise, it works like this:
required fields:
rid -- the relationship id. just an auto-id to give us something concrete to connect to. term_node lacks this, and it's a PAIN.
source_nid
target_nid -- the two nodes being connected to each other
relationship_type -- a simple descriptor like 'child' for a book page or 'comment' for a comment or 'describes' for a taxonomy-term-as-a-node.
optional fields:
uid -- the user that created the relationship. -1 would be used for system-level relationships, probably. not auto-populated.
created -- a timestamp. auto-populated.
weight -- for relationship ranking. defaults to zero.
The API itself consists of a handful of core functions:
relationship_set($source_nid, $relationship_type, $target_nid, $uid = NULL, $weight = NULL, $table = 'relationship')
relationship_get($source_nid = NULL, $relationship_type = NULL, $target_nid = NULL, $uid = -1, $table = 'relationship')
relationship_unset($source_nid = NULL, $relationship_type = NULL, $target_nid = NULL, $uid = -1, $table = 'relationship')
There are discrete insert/update/delete functions too, but the above are designed so that most modules can use them exclusively. NULLs passed in act as wildcards right now; I'm sure that should be changed to enums for safety's sake on the unset operations. The idea is that you can retrieve 'all child relationships where the source node is 1' or 'all relationships between nodes 3 and 6' or 'all descriptive relationships created by user so-and-so.'
The goal is pretty simple; make something that's capable of capturing a laaarge superset of linking tasks, but leaves the complexities up to the modules that manage the relationships themselves. This standardizes the relationship data storage, it doesn't attempt to implement things like synonmous and inverse relationships, etc. There's even a final parameter -- $table -- that works a lot like cache.inc's table optimizations. It allows modules to split off a subtable if they need high performance for their particular relationships.
It's small, it's lean and mean, and the schema is simple enough to be queried directly by those who need it. Any thoughts? Anyone?
| Attachment | Size |
|---|---|
| relationship.inc_.txt | 2.95 KB |
| relationship.install_.txt | 901 bytes |

Comments
module
hi eaton. looks real nice. i think it should be a module instead of an .inc. that way we avoid a problem if it gets popular and a site wants to use 2 modules that depend on it.
i would be interested to seee one or two modules rewritten to use this instead of custom relationship. maybe buddylist or views_bookmark?
Possibly
I have a 10-line .module file that does nothing but wrap an 'include' around this; the idea was to release it as a 5.0 module, and lobby for just the .inc to be included in core. Thus the extremely lightweight nature of it...
I'm not sure views_bookmark would make sense for it, as that's more of a 'marking' tool than a 'relationships between nodes' module. Things like book.module, casetracker.module, nodereference.module, and so on are all examples of what might make more sense to port to it. Hmmm. Hacking book.module to use this, and calling it 'outline.module' as a demo, might be a nice example. Hmmmmm hmmm hmmm.
I'll try to think of a name for it that doesn't conflict with an already existing contrib module, and release it for Drupal 5 this evening.
Node centric :(
With one more column - 'entity' - we could break the node-centric limitation and you could do views_bookmark with it, because that marking tool is also a relationship; a relationship between a user and a node.
The only problem...
......Is what I ran into with VotingAPI. When you abstract out the table name, you remove your ability to easily do some kinds of joins and so on. Making everything a node simplifies that considerably...
What I did think of last night was a system whereby any user can create a 'bookmark' node that becomes the central point around which those queries can revolve. A profile node would be the central point around which a buddy list could revolve, too...
Do you think that would work as well?
no like
i don't like making everything a node. we aren't ready for that now, and might not ever be ... i would prefer to lose the 'user whatever table you want' feature.
further abstraction
Perhaps we need a further abstraction.. e.g. drupal objects, with the sub-types nodes, users, comments,..
Then we could build things on top of this - e.g. unified loading and saving functions, views and relations.
Views went down this road
+1 to Robert's comments.
Views started as a "we only do nodes, buddy" module, but the clamor to build queries of other data types (e.g. users) is now a maddening roar.
I believe Earl has promised other tables as an option for Views 2.0
I think it would behoove the relationships API to skip the "nodes only" release and cut right to a generic table situation.
I wonder if our ability to reliably construct sub-queries could come in handy now? Perhaps in addition to rid, etc we also store 'table' in the schema. Do a sub query to find all the tables (eg. SELECT table FROM api WHERE some qualifications GROUP BY TABLE) and then join across those tables. Though this may not be possible without a procedural language (at least to do everything at the db level).
We could always make postgres a requirement for the relationship api. ;-)
-Mark
Open to this
I'm definitely open to this, as long as we can figure out how to do it without making the api for it a lot more complicated OR making the queries a lot slower. The simplicity of just using 'get/set' and having a limited set of parameters is an advantage. If we want to relate different kinds of things to each other, we'll need a 'thing_type' for each ID, which bloats the parameter set up pretty quickly.
I'm not against it, I'm just concerned that it would make things more confusing to work with when nodes are the super-common case.
Thanks for the feedback. I'm really hoping that we can get some momentum behind this 'bare bones' approach, and allow other systems to implement the wild and crazy stuff (RDF triples, relationship inversion, etc) on top of it rather than wedging the heavier features into core...
module name
let us know when the module is committed and its name. thx.
what is the project?
Has this been released?
thanks,
augustin.
--
www.reuniting.info
Healing with Sexual Relationships.
www.wechange.org
We live in a world of solutions.
.
--
www.reuniting.info
Healing with Sexual Relationships.
www.wechange.org
We live in a world of solutions.
Spiffy
Nice. I agree that a common storage engine for node relationships is a good thing. However, how would one build efficient recursive relationships with get/set functions? For instance, take the comment tree. It would get very SQL-expensive to stick with the get/set functions.
I think performance over a large number of nodes (eg, displaying graphs of nodes, possibly in Views possibly not) would be the main bottleneck for any simplified relationship API.
Some solutions
Indeed -- I'd suggest those would be good candidates for specialized optimized tree selection functions.
Here's a sneaky bit. Because we can store more than just a single kind of relationship, we can do a lot of creative things. For example, one might consider storing a relationship for a leaf back to each branch in the tree it's part of, all the way to the trunk node. That would allow single-query lookups of the entire parent tree for a node. The 'weight' flag could be used to indicate the depth of each individual relationship.
And very data intensive kinds of relationships could be moved off to separate tables as needed.
i like it its pretty similar
i like it
its pretty similar to what i'm doing, except your function names are cleaner
there is one important thing though that i think you're lacking
in real life, you can relate a car and a person
Bob owns Car X
but, thats not the only type of relationship that can exist between a person and a car
a person could also be the mechanic for a car, or previous owner, or any of many things
so, I think its important not just that two things are related, but also to label what type of relation it is
i've implemented such a system for my cck subform module
basically you define "types" of relationships that can exist, and then you define relationship instances to actually connect objects
these relationship instances refer back to some relationship type record, so you know what kind of relationship instance it is
there are some drawbacks to my system, the biggest one is that relationship types can only be defined amongst CCK content types, and currently I provide no support for relation cardinality restriction or friendly labeling from one point of view or the other
anyway, if you wanna check out what i've got, feel free at http://subform.googlecode.com/svn/trunk/subform_trunk.zip
but you're right, one way or another, relationships between things is a pretty integral idea. and should probably be in core in some form or fashion
whatever eventually does get into core, i'll just end up connecting to that anyway for my subform gui
so i wish you the best
It's there...
That's what the 'relationship_type' field is for; when relating a person and a car, as in your example, you could put 'mechanic' in that field.
It's nice to finally get
It's nice to finally get some code for this!
Things I like:
Things I think need work:
To get beyond that we need to start doing selective denormalization, SQL tree mappings or external tools such as the Arc RDF store. These work great - but don't always cross use-cases very well. For example, SQL tree mappings are great for hierarchical relationships, but are difficult to use for non-hierarchical network relationships.
I discussed the above points quite a bit with my original Relationship API suggestion http://groups.drupal.org/node/245. I started writing code for this a few times but never got very far. I'll try and write up some more detail of some of the problems I encountered and possible solutions, and perhaps we can start kicking this into action.
Indeed...
Indeed. Everybody's made that point so far and I yield. ;-) Making everything in Drupal a node is a good thing, IMO, but a separate issue from the relationships question. It should be done, and robert has suggested a relatively small addition to this API that would make it possible.
I'd definitely be interested in this, though it already supports specifying alternate tables which could contain their own additional columns, but I'm pretty sure that's not what you mean. My question, though, is this: why would a system of the complexity you are describing even need to go through this API? Couldn't it simply do its own thing?
The purpose of this API is to simplify something that comes up over, over, over, over in Drupal: linking arbitrary stuff together, building simple trees, and so on.
That sounds interesting. Would it be possible to create a relationship_tree table, for example, that includes one extra field, the flattened hierarchy? Or perhaps the 'alternate table' approach I've outlined is insufficient.
when whipping this up, I decided explicitly to avoid many of the high-end features. An earlier version of this code did allow for some of the stuff you describe -- storing relationship definitions, defining inverse and synonymous relationship types, etc. But in the end it added a LOT of cruft and gained very little; implementing crazy stuff like RDF on top of it would still take tons of additional code, and the simple cases (adding buddies, bookmarking nodes, definig book hierarchies) didn't benefit. We've spent years kicking around talk about the need for a simple relationships API in drupal, and it seems like things always stall around the relatively esoteric big picture features. Why not implement the 'simple' cases? It's an improvement over what we have today, and doesn't block anyone from implementing something more complex.
I'm open to anything that makes the esoteric and specialized stuff possible, I'm just kind of skeptical after ~2 years of making noise on relationship apis. I've heard and seen lots of huge plans for all-encompasing metadata frameworks... After all that time, the best general use tool we have to connect things together is still CCK's nodereference field.
I Agree }:-/
I completely agree with the 'cruft' comments.
(Sorry I haven't replied earlier, but had big - actually paying - projects on)
As soon as I got one thing (relationships) managed, I went on and abstracted the management (domains and range restrictions) then abstracted the management management (ontologies) and well ... it's all a bit abstract when all you wanted was a related comment link :)
My alternative to 'everything is a node' was 'everything is a URI'
Thus I was able to create relationships between users /user/12 and terms taxonomy/term/13 and node TYPES and all sorts.
The subject/object indexes in the triplestore are strings, not numbers.
I looked at the scaling and flattening problem as an 'aggressive' or 'passive' flag on the storage engine. An aggressive triplestore manager would take reltionships put in and internally populate and memo all the later implied relationships the rules propogated. This gives you the 'flattened' behaviour needed for responsiveness.
The derived triples are also tagged with a derivation depth, so they can be culled or flushed.
And yeh, the storage engine SHOULD be pluggable with a bigger, badder triplestore manager. But I didn't puse further in that direction until I knew what I wanted from it.
I't love to clear some of the cruft, and release a slimmer version, but I'm getting paid too much to do real-world (though less interesting) things at the moment. :-/
.dan.
You're right.
I spent this weekend beginning to tackle comments-as-nodes, and used this relationship API as a starting point. I'm beginning to realize that you're right: different applications of the relationship API will want to tag different meta-data onto their linking records.
Because of the relative simplicity of the API right now (get and set are relatively straightforward) I think I'd like to release this as a module for Drupal 4.7 and 5.0. Once there's some feedback in place, I'd like to look at the kind of stuff you're talking about: pluggable backends and ways of capturing more meta-data for each relationship record, and the flexibility to relate anything-to-anything. 'node' could serve as a default for both the source and target, but could be changed to anything else.
It's times like this that I wonder whether a keyed array would make a better parameter for something like this. I know that it was unpopular with node_load(), but it seems like it could really help here, where there's a long list of optional parameters that can interact in different ways.
for example:
<?phprelationship_set(array('source'=>1, 'relationship_type'=>'parent', 'target'=>2, 'table'=>'my_custom_table'));
?>
Any thoughts?
This is a parent-tree
This is a parent-tree implementation right? Each member of the tree has a source_nid (which is its direct parent) except for the root of a relationship.
This would be great. It makes it really easy to join relations, find sub-relations and do a whole bunch of different things.
Perhaps make a valid_relationships table (awful name, but it conveys idea) that contains the valid possible relationships AND the specify the content types of the relationships (Related Forum Topics would only relate to forum topic nodes and not comments). More I think about that idea the more I don't like it but figured it would stir some discussion
domain and range restrictions
The terminology you need is Domain and Range.
as defined by RDF Syntax etc
I supported this with my relationship efforts - just to make the UI more intuative - but managing THEM looks complicated.
.dan.
Node relativity
I like this API - it's simple, and it's here. I could see rewriting Node Relativity to use it. I would think we should set a limit on discussions/features/modifications and then just commit this API as a module, so something concrete comes out of this.
Darius
Cool! +1 to get this into
Cool! +1 to get this into drupal 6, and have it replace ancient tables like node_term, and implementations like nodereference.module and userreference.module
I like this idea too
Here's an issue with nodereference where I think a Relationship API would help. I had already commented there, but never provided any code. :-/
// David Lesieur // Associé // Whisky Echo Bravo // Développement Web, experts Drupal // Montréal //
Looking forward to this!
If there's some financing needed to help it along, that's probably the least I can do.
~ In living, loving memory: http://melanconent.com/john-melancon-life ~
benjamin, agaric
Very needed ...
Is there maybe a status update on this?
And in the drupal 5 context we should probably make this a module and not just an inc-file?
--
best regards
Ray
If you need a drupal developer contact me!
--
best regards
Ray
If you need a drupal developer contact me!
Yes it's exacty wath i search...
I see the http://drupal.org/project/relationship module but is inactive, it's very big, and don't work on D5...
I need a RDF approach with a user interface to link the node (and user...if this is not too hard). So like ray007, I says, "what it's the status of this code"?
I'm interesting to help the dev of the module with test, debug and GUI design. I have not enough experience (yet) with drupal to develop from scratch without do big issue :/.