Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defined active record model's HABTM associations #8

Open
jlforever opened this issue Jan 10, 2015 · 6 comments
Open

Defined active record model's HABTM associations #8

jlforever opened this issue Jan 10, 2015 · 6 comments

Comments

@jlforever
Copy link

It looks like the Neo4Apis::ActiveRecord:: model_importer method is able to handle has_one, has_many and belongs_to reflected associations, which in most cases will be able to handle most of the 1:M, M:1 or M:M (with intervening model that links the many to many related tables, ex: projects, researchers, advisors: a project has many advisors through researchers) relationships.

However for a direct M:M relationship, with no intervening model (departments, employees departments_employees for example), which model wise, can be defined with the has_and_belongs_to_many association within the Employee and Department models, will the relationship, translated into neo4j appropriately, even though it is not a handled association?

@cheerfulstoic
Copy link
Contributor

It's true! I would definitely like to add HABTM associations. If people do a table import then it will actually import these associations as nodes, but if they're importing from an existing ActiveRecord app then it won't.

I'm wondering if there should be an option to import tables with two foreign keys as relationships rather than nodes with two relationships and to put the key/values from that table into the relationship. Maybe when importing models it should always do this for has_many :through and has_and_belongs_to_many. What do you think?

@jlforever
Copy link
Author

I agree @cheerfulstoic and thanks for the prompt reply.

I think when importing AR models, it should, like you've mentioned, keep the defined association for has_many :through and has_and_belongs_to_many as relationships (or edges, is that the right term, still not familiar with neoj4 terminologies).

This will ensure that the referential integrity of the related models, when translated into neo4j land as model -> node, then, either the nodes are linked when foreign keys are matched, or dangling when M:M table doesn't have an entry to associate the models, or the has many through relationship's through relationship is not defined, so that there isn't a 1:M relationship either. What is an edge for a M:M relationship like in neo4j land?

For straight table import, with no definitive relationship, will neo4j, allow you to define relationships to link the nodes, once tables are imported as nodes?

@cheerfulstoic
Copy link
Contributor

So neo4j's modeling is pretty simple. There are nodes and relationships. Both can have key/value pairs to store data. Nodes can have 0 or more "labels" (like User, Post, Comment, etc...) while relationships are required to have just one "type" (like wrote_post or comments_on, etc...). In neo4j terminology, relationships match the idea of "edges" in mathematical graph terminology.

So in neo4j, you can have 1:M and M:M, but they're modeled the same way: as relationships between nodes. If nodes of a particular label always happen to have many nodes leading to one node, then that could be considered 1:M, but there's nothing stopping it from being M:M. You might even say that all relationships in neo4j are M:M because relationships are a separate data store from nodes and they can always link any node to any other node.

So if you use the all_tables command in neo4apis-activerecord, it will read through your tables generate ActiveRecord models by looking for primary keys and for primary-key-like-columns. The primary keys become neo4j indexes and the primary-key-like-columns get imported into neo4j, but they also get imported as relationships. So if you have posts and comments tables where the comments table has a post_id, then the Comment nodes will also have post_id keys, but there will also be a relationship from Comment nodes to Post nodes with the relationship type post.

So, with that background, to make sure that I'm being clear in my proposal:

With both has_and_belongs_to_many and has_many :through you have in SQL a third M:M table. The difference between them is that has_many :through has an ActiveRecord model in between because you need to do something more with them (store additional data, run validations/callbacks/whatever).

If a user of neo4apis-activerecord uses the all_tables command then obviously we don't know if they would have modeled a join table as has_and_belongs_to_many or has_many :through, though normally people only use HABTM when they have a M:M table with a primary key and two foreign keys, and they use has_many :through when there are more columns than that.

Either way, though, I can imagine that a table with two foreign keys could naturally be modeled as a relationship because there is a connection between the two (although direction isn't usually clear). Even if it's has_many :through, you can store data on the relationship and in the neo4j gem you can optionally model relationships with the Neo4j::ActiveRel module, which approximates a has_many :through association pretty well.

So the point of that was mainly to explain how neo4j works and how neo4apis-activerecord works, but it's also kind of helped my talk (or at least type) things out. I think that there should be a command-line option to import tables with just a primary key and two foreign keys as relationships, but otherwise it just imports tables as nodes and creates relationships for any foreign key references. When importing ActiveRecord, I think that all HABTM and HMT associations should be relationships.

What do you think? I'd also like @subvertallchris 's opinion as well ;)

@jlforever
Copy link
Author

@cheerfulstoic thanks for explaining some of the neo4j basics.

I think having another option for neo4apis-activerecord to tell whether to import a table with 2 foreign keys, which acts as a join table, as relationships, makes sense. Without the option, it will just default to be imported as a node.

@cheerfulstoic
Copy link
Contributor

Just ran into this on the neo4j developer resources pages:

http://neo4j.com/developer/graph-db-vs-rdbms/#_data_model_transformation

Putting here for reference as I think it's very appropriate to the gem

@cheerfulstoic
Copy link
Contributor

FYI I just implemented HABTM in version 0.7.0! It works if you already have it defined in your models. Haven't yet played around with building in assumptions based on table structure when there are no models

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants