dresende / node-orm2

Object Relational Mapping
http://github.com/dresende/node-orm2
MIT License
3.07k stars 376 forks source link

Does node-orm2 support polymorphism association ? #108

Open chenghung opened 11 years ago

chenghung commented 11 years ago

hi all: Does node-orm2 support polymorphism association ? I need it to define my models just like following example.

============================= example ============================= person has many pets

pets could be either 'dog' or 'cat'

person table id name

person_pets table # the association between person and dog/cat person_id pet_id # pet_id is id of dog table or id of cat table pet_type # pet_type = 'dog' or 'cat'

cat table id name

dog table id name

dresende commented 11 years ago

It doesn't support. It shouldn't be too hard to implement, but for now it's not that easy to have that kind of associations.

dresende commented 11 years ago

I was about to pick this up but have many doubts about how to implement this. In theory is easy but for example, it's very hard to implement this with chaining:

Person.getPets(function (err, pets) {
    // somewhat easy..
});
Person.getPets().run(function (err, pets) {
    // hard
});

Easy and hard are just about lines of code that have to be changed, not that it's really hard. I still would like to do this but I still have to think more about this.

ProCynic commented 11 years ago

I really need something like this too. But I prefer a setup where the primary keys of the cat and dog tables are foreign keys into a pets table. Then the pets table has a standard many-to-one relationship with the person table. So it looks like this:

person

pet

cat

dog

You maintain normalization, you can never have a cat or dog that isn't a pet, and you have a standard relationship between pet and person. The downside is you have to join with pet every time you use cat, but the orm should handle that if you tell it that cat extends pet.

EDIT: Having a cat model extend a pet model similar to how Backbone.Model.extend works would be ideal.

dresende commented 11 years ago

I'm trying to make this in a new branch (not published yet). What I'm trying to accomplish is something like:

var Pet = db.define("pet", {
    name : String
});
var Dog = db.extend(Pet, 'dog', {
    weight: Number,
    // ...
});

You would then use Dog or other extensions to look at your data. I'm not sure this solves everything but with some more additions people could use Pet.find and have returned a list of Dog, Cat, whatever, .. I'm not sure this is the expected behaviour..

noazark commented 11 years ago

Isn't this more single table inheritance and less polymorphism? Polymorphism would look more like:

var Pet = db.define("pet", {
    name : String
});
Pet.hasPolymorphicOwner("owner") // this also could be `hasOwner("owner", {polymorphic: true})`

var Person = db.define("person", {
    name: String
});
Person.hasMany("pets", Pet, {as: "owner"})

var Store = db.define("store", {
    name: String
});
Store.hasMany("pets", Pet, {as: "owner"})
dresende commented 11 years ago

Could you please elaborate on your example? I'm having some trouble detecting the tables behind it and the polymorphism.

dxg commented 11 years ago

I've rewritten the above with a more orm-like syntax, and different names:

var Comment = db.define("comment", {
  text: String
});
Comment.hasOne("owner", { polymorphic: true, reverse: true, autoFetch: true });

var Article = db.define("article", {
  title: String,
  text: String
});

var Photo = db.define("photo", {
  url: String
});

Article.get(4, function (err, article) {
  var comment = Comment.create(text: "hello"); // creates comment with id = 7
  comment.setOwner(article, ...);
});

...

Comment.get(7, function (err, comment) {
  comment.owner_id   // 4
  comment.owner_type // article
  comment.owner      // article instance with id 4
});

Schema

Comment
id:         SERIAL
text:       VARCHAR(1000)
owner_id:   INTEGER
owner_type: VARCHAR(255)

Article
id:         SERIAL
title:      VARCHAR(255)
text:       VARCHAR(20000)

Photo
id:         SERIAL
url:        VARCHAR(2700)
buehler commented 10 years ago

:+1: for single (or multi) table inheritance of objects, would be a nice feature. expected behavior would be as dresende described in his post (https://github.com/dresende/node-orm2/issues/108#issuecomment-19046081)