开发者

Working with cyclical graphs in RoR

开发者 https://www.devze.com 2023-01-25 11:53 出处:网络
I haven\'t attempted to work with graphs in Rails before, and am curious as to the best approach. Some background:

I haven't attempted to work with graphs in Rails before, and am curious as to the best approach. Some background:

I am making a Rails 3 site and thought it would be interesting to store certain objects and their relationships as a graph, where each object is a node and some are connected to show that the two objects are related. The graph does contain cycles, and there wouldn't be more than 100-150 nodes in the graph (probably only closer to 50). One node probably wouldn't have more than five edges, with an average of three to four edges per node.

I figured a simple join table with two columns (each the ID of the object) might be the easiest way to do it, but I doubt it's the best way. Another thought was to use a plugin such as acts_as_tree (which doesn't appear to be updated for Rails 3...) or acts_as_tree_with_dotted_ids, but I am unsure of their ability to work with cycles rather than hierarchical trees.

the most I would currently like is to easily traverse from one node to its siblings. I really can't think of a reason I would want to trave开发者_Go百科rse to a node's sibling's sibling, which is why I was considering just making an SQL join table. I only want to have a section on the site to display objects related to a specified object, and this graph is one of the ways I am specifying relationships.

Advice? Things I should check out? Thanks!


I would use two SQL tables, node and link where a link is simply two foreign keys, source and target. This way you can get the set of inbound or outbound links to a node by performing an SQL select query by constraining the source or target node id. You could take it a step further by adding a "graph_id" column to both tables so you can retrieve all the data for a graph in two queries and build it as a post-processing step.

This strategy should be just as easy (if not easier) than finding, installing, learning to use, and implementing a plugin to do the same, IMHO.


Depending on whether your concern is primarily about operations on graphs, or on storage of graphs, what you need is potentially quite different. If you want convenient operations on graphs, investigate the gem "rgl" (ruby graph library). It has implementations of most of the basic classic traversal and search algorithms.

If you're dealing with something on the order of 150 nodes, you can probably get away with a minimalist adjacency list representation in the database itself, or incidence list. Then you can feed that into RGL for traversal and search operations.

If I remember correctly, RGL has enough abstraction that you may be able to work with an existing class structure and you simply provide methods to get adjacent nodes.


Assuming that it is a directed graph, use a mapping table such as

id | src | dest

where src and dest are FKs to your object table.

If your objects are not all of the same type, either have them all inherit a ruby class or have another table:

id | type | type_id

Where type is the type of object it is and type_id is its id in another table.

By doing this, you should be able to get an array of objects for each object that it points to using:

select dest 
from maptable 
where dest = self.id

If you need to know its inbound edges, you can preform the same type of query using src instead of dest.

From there, you should be able to easily write any graph algorithms that you want. If you need weights, you can modify the mapping table as such.

id | src | dest | weight
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号