I was wondering if any module developers have been faced with representing m-n relationships between nodes and how this was accomplished. I'm currently faced with the task of mapping a user interface on top of a dozen or so distince data types (tables), each of which is somehow related to the others (through foreign key relationships).

I've seen how the project.module has projects that contain issue nodes and release nodes, but that seems like a much more laborious setup than anything I need. The table structures would look something like the following:

parent_table:
  nid int,
  parent_stuff varchar(255),
  other_stuff varchar(255)


child1_table:
  nid int,
  parent_nid int,  // foreign key into parent_table
  child1_data varchar(255),
  child1_more_data date


child2_table:
  nid int,
  child1_nid int,  // foreign key into child1_table
  child2_other_data varchar(255),
  child2_yet_more_data int

Each node of all types would exist on its own, but nodes of type child1 would have to be associated with a parent node, and nodes of type child2 would have to be associated with a child1 node.

Even if the child1 and child2 types didn't need to exist (as distinct nodes) outside of the scope of the parent node, there would be multiple child1 records for each parent record. Does anybody else do this sort of thing using the node system? I have some ideas for how to deal with this, but they're all kinda clumsy and/or very code intensive. Generally, there isn't much that needs to be done with each data structure other than providing edit facilities and rendering it for viewing. If I thought I could do this using flexinode.module, I certainly would.

I would appreciate any input any of you have.

Comments

javanaut’s picture

I'm quickly hacking something together for a project that will eventually be a useful module here. It is another option that was discussed when the attached_node and attached_file modules were created.

The purpose is to allow users to specify parent/child relationships between nodes. There is a feature that lets the admin limit what types of nodes can parent what other types of nodes. This has made rather simple work of my 17-entity design by using flexinode nodes to represent the various data types and this module I've written takes care of the relationships between them.

I still don't really have a name for it, but it'll be ready for testing soon if anyone is interested.

robclay’s picture

To understand better, this is what I think this will do: I have some different types of flexinodes for a site that promotes dancing. One flexinode is "lessons" for instructors to post about their lessons. They can also post an event, but it is not tied to their lesson... I would like them to be able to post their lesson - and then they can have events under their lessons, e.g.

FLEXINODE-1 (Lessons): Tom & Jerry: Cat & Mouse Dance Instructors
EVENT - Beginning cat & mouse dance moves on Jan 30
EVENT - Advanced Cat & Mouse moves on Feb 15th
EVENT - Beginning Cat & Mouse moves on March 23rd.

So when they click on the Tom & Jerry: Cat & Mouse Dance instructors, the event nodes come up as well?

javanaut’s picture

Currently, only the titles of the events would show up when you viewed a lesson, but this would be easy to theme such that the entire event would be viewed instead.

On the edit page for the Lesson node would be 2 links: one to create a new Event associated with the lesson, another to choose from a list of existing Events. You would specify that Lesson nodes could have Events as children on the settings page for this module.

I'd say it's 85% complete, with all major features implemented, though still slightly buggy. I should have it in CVS sometime tomorrow.

I'd like to add a link to nodes that have parents linking to all of their parent nodes, but I don't currently have a need for it, so it's lower priority.

javanaut’s picture

..but it's still not ready. If you feel like playing with it, I've placed it in my sandbox here:

http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/javanaut/node...

javanaut’s picture

Added many user interface pieces.
Added a block for ancestor navigation.
Added (currently ugly) tools to attach and remove nodes.
Added more permission logic, making it such that node types that require a
parent to exist are not listed in the "attach existing node" list.
Altered "add existing node" SQL to exclude nodes that are already attached.

Still need to use node_access join and pager_query for listing existing nodes.
Still need to clean up add/create/remove links interface, as they
are currently ugly.

I'm still not sold on "nodeattachment" as the module name. How does "noderelations" sound? Anyways, I should write up a README.txt sometime soon and get it into it's own module directory.

robclay’s picture

I am not sure about the name either!

But I am very unfamiliar with the whole CVS thing... (shame on me) I have tried without success. When it is ready to try out as a regular module I will let you know how it goes!

- Robert

javanaut’s picture

I was thinking "relativity"..as it defines relationships between nodes as relatives of one another.

You're probably better off waiting until it's a bit more stable, as I seem to find new outstanding bugs with some frequency :)

If you do get curious, though, you can download the cvs HEAD version directly. You'll also want the MySQL script to create the table.

javanaut’s picture

..and quite a few bugs stomped out. I'll probably move it into it's own project in the main repository early next week. I'm about to put it into production internally late next week, so I hope it works with few problems :)

I think this will be extremely useful along with flexinode for developing rapid applications.

Still todo:

I intend to build a search mechanism for searching through a tree of related nodes for some content item. This won't be implemented too soon, but I think if you're going to maintain content as part of a network of related nodes, you need a way to search/sort/navigate display it.

Sooner than that should be a DHTML tree navigation. Most likely, lots of code will be borrowed from the various taxonomy-based browsers that perform visually similar tasks.

Bèr Kessels’s picture

I made a module that does this, using taxonomy. It can be found under the name of clipper.module.

And if this solved you problem, would you be so kind to report back that it helped? This will help others whom are looking for the same solution.

[Ber | Drupal Services webschuur.com]

javanaut’s picture

I haven't tried it out and couldn't say whether it fits my needs or not, but it does look similar (just browsing the code). I'll have a look tomorrow and let you know what I find.

Thanks!

javanaut’s picture

That's a very interesting module. With it, you're automatically binding node types to taxonomy terms, but not each other (from what I could tell testing it out). I need a means of associating individual nodes with each other, but restricting which ones can be associated by using the node's type.

By restricting the types of nodes that can be bound to a given node, it allows me to display links to create new nodes that are automatically associated with the parent node (or attach existing ones). Sound confusing? It currently has my head spinning just talking about it.

A simple example would be a blog post where once the blog post was saved, you could associate an image node to it. You could make a rule that says that images can only exist if they are associated with blog nodes. I can see much potential for such a node relationship manager, which is why I was surprised to find that one didn't seem to exist. I know it has been discussed on many occasions already.

javanaut’s picture

Ok, this little project has taken on a very useful role in the project that I'm working on. It's quite an interesting means of representing drupal nodes as nodes in a Directed Graph. The relations represent directed edges connecting the nodes of the graph. This allows very complex data structures to be created with relative ease, and those data structures can be sorted, searched and traversed using various Graph traversal algorithms.

I'm currently working on a recursive function that "walks" the graph starting from a node, applying filtering rules for direction, distance and node type. It will return an array of all nodes that meet the search criteria. I'm now working on a query builder that lets you specify all of the search parameters. Currently, this includes direction (follow parents, children or both), recursion depth (how far from the starting node to search), end points (what types of nodes to stop searching beyond) and avoidance points (what types of nodes to avoid altogether).

A module that is similar to this one is the book module. A book could be seen as a graph of nodes where the book module maintains the relations between them. It is generally seen as unidirectional, but to a graph theorist, looks fairly similar. If a book-like construct were created using this tool, it could be traversed in any direction. For instance, you could say: "show me all image nodes in Chapter 3 of this book" and it would perform a depth-first-search through all content in "Chapter 3" looking for image nodes. You could query for "every filestore2 node within 6 pages of this one" for instance. Since the underlying table structure of the book module is similar to this one, I might port this search tool over to the book module if it turns out as pretty as I'm hoping it will.

I will be creating a proper project for it sometime this week, probably before I'm done with the user interface to the query tool (though developers can call the API directly).

javanaut’s picture

The project page can be found here:

http://drupal.org/node/17004

Enjoy!

Aran Deltac’s picture

I'd love to use this, but when I go to your link all I get is a description. How do I download it? What is it's current status? Is it designed for 4.5? Is it "production" quality?

--
http://www.electroniclife.org/

javanaut’s picture

I don't know why the project's not showing up. It could be generated on a nightly basis.

You can grab it directly from CVS here:
http://cvs.drupal.org/viewcvs/drupal/contributions/modules/relativity/

Since I just wrote it over the past week, I wouldn't say that it has any track record to speak of. I did develop it on version 4.5.2, so it's somewhat current. I'm currently using it as part of a relatively small internal application. If you have massive amounts of content, I can tell you now that some of the screens will probably look ugly at this point. Functional, but ugly. For instance, when searching for existing nodes to attach as children, the results arent paginated, so you'll get all nodes of a given type listed out before you. It's on my todo list and should be cleaned up soon.

Aran Deltac’s picture

Very very very very very very nice!

Good job.

The only thing I can see so far that I would want added is that when viewing a child node it would be nice to be shown what it's parent's are (similar to how a parent has a list of child nodes).

Thanks!

--
http://www.electroniclife.org/

javanaut’s picture

That's one thing I was considering..for now, there's a block that displays parent information. You should enable that for breadcrumb-like navigation. It disappears when no parent info is around or could be found. I just realized that the block isn't mentioned in the README.txt file. I'll add it later.

I suppose it would make sense to include it into the body of the node, but it's already getting too cluttered for my purposes. It would be fairly easy to add this as an optional feature (configured on a per-type basis).

Aran Deltac’s picture

Cool, the block works.

Still, the ability to choose the parent node during a child node's creation is the only thing barring me from useing relativity.module. Is this a simple change to make? Complicated?

--
http://www.electroniclife.org/

javanaut’s picture

There's some code that's commented out in the relativity_nodeapi function under the "view" section, but I don't recall if it's still valid (and my code's too far beyond what's in CVS to accurately test right now). I'm working on the query tool, and once that's done (probably today, maybe tomorrow) I'll upload a version that optionally includes this option.

Aran Deltac’s picture

Great, thanks dude. I'll keep my eyelids pealed.

--
http://www.electroniclife.org/

Aran Deltac’s picture

This is how I've implimented your relativity module, check it out:

http://www.electroniclife.org/node/32

It doesn't work perfect and hides information I would like shown, and lays out some things odd (the block doesn't look "right"). But, I know you threw this thing together in record time - and the functionality is great!

javanaut’s picture

Cool. I'm almost finished with the frontend for the query tool, but it won't be ready until tomorrow. Hopefully, the project page will be working for me by then.

BTW, your site looks quite interesting. I've been researching artificial neural networks for their potential in mining data and pattern optimizing, mostly within the realm of social network analysis. I'll definitely be keeping an eye out on your site.

Aran Deltac’s picture

The project page is working!

I went ahead and posted several feature requests. Much more organized to create issues than keeping on posting to this topic. I'd be happy to hack away at your code if any of these features are thing that you don't have time or desire to work on.

http://drupal.org/project/issues/relativity?categories=feature

Let me know when you have that new version released.

Aran

--
http://www.electroniclife.org/

javanaut’s picture

I'm done with a first-round version of the query tool, and I've added a few goodies to the admin/settings/relativity page.

Because I know you like reading CVS commit logs, here's the abbreviated version of what changed today:

added perm hook
added access hook
added relativity_query node type and all associated API hooks
added connected node query tool via relativity_query node type
themed much previously unthemed output
added Depth-First search algorithm
fixed various bugs in previous implementation
added search type and max_results fields
log node visits and don't return to previously visited nodes
refactored code to simplify the
addition of other search algorithms.
Made nodeapi('view'..) output configurable in admin/settings/relativity
made a few convenience functions

BTW, I'm hesitant to commit this to 4.5, so for now, these changes are in CVS HEAD only. I'll update the README soon to reflect these changes.

Aran Deltac’s picture

Wow, this module is really coming along. Good job.

The query node looks great. What you are makeing is so versatile that it seems like something that should be in the core at some point.

I did have one issue tho:

http://drupal.org/node/17141

--
http://www.electroniclife.org/

Aran Deltac’s picture

When createing a node that has parents defined for it, it would be nice to be able to choose which of the existing parent nodes belong to it.

Right now I'd have to first create the child node, then find the parent, and click assign existing node.

Also, if you made the parent selection process a part of the child creation process then it would be nice if it was optional to display the "assign existing child node" from the parent node's view.

--
http://www.electroniclife.org/