I'm still new to mongo_wrapper so I hope my question isn't due to my
lack of knowledge.
I want to link two models in a way that I haven't seen examples of yet
with mongo_wrapper:
Model ContentType: name[String].
Model Relation: Each Relation has 2 ContentTypes referenced. rel.from
= [ContentType] rel.to = [ContentType]. Embedding is not an option
since each ContentType can belong to multiple relations.
So basically I have a [ContentType] N:N [Relation], [Relation] N:2
[ContentType] association model.
How can this be done? I tried in the Relation model:
one :content_type, :in => :from
one :from, :class_name => 'ContentType'
and other variations with :typecast eg.
Simply storing the respective _id's as ObjectId is no problem, but
then rel.from is just an id and I have to do the lookups myself via
ContentType.find(rel.from).
The only way I got this working is in the console with
c1 = ContentType.create
c2 = ContentType.create
c1.save!
c2.save!
rel = Relation.create
rel.from = c1
rel.to = c2
rel.save!
rel = Relationship.all.first => right ContentType
But then, rel doesn't save the _ids of the ContentTypes, rather the
_id of the Relation is saved in the content_types' relationship_id
field, which I don't find optimal and adds complexity to simple crud
operations.
Help is greatly appreciated, I hope my problem is clear.
> I'm still new to mongo_wrapper so I hope my question isn't due to my > lack of knowledge.
> I want to link two models in a way that I haven't seen examples of yet > with mongo_wrapper:
> Model ContentType: name[String]. > Model Relation: Each Relation has 2 ContentTypes referenced. rel.from > = [ContentType] rel.to = [ContentType]. Embedding is not an option > since each ContentType can belong to multiple relations.
> So basically I have a [ContentType] N:N [Relation], [Relation] N:2 > [ContentType] association model.
> How can this be done? I tried in the Relation model: > one :content_type, :in => :from > one :from, :class_name => 'ContentType' > and other variations with :typecast eg.
> Simply storing the respective _id's as ObjectId is no problem, but > then rel.from is just an id and I have to do the lookups myself via > ContentType.find(rel.from).
> The only way I got this working is in the console with > c1 = ContentType.create > c2 = ContentType.create > c1.save! > c2.save! > rel = Relation.create > rel.from = c1 > rel.to = c2 > rel.save! > rel = Relationship.all.first => right ContentType
> But then, rel doesn't save the _ids of the ContentTypes, rather the > _id of the Relation is saved in the content_types' relationship_id > field, which I don't find optimal and adds complexity to simple crud > operations.
> Help is greatly appreciated, I hope my problem is clear.
Yes, but the relation I aim for is not in the docs.
One-to-Many doesn't work because I need 2 belongs_to statements in my
Relationship-Model
Many-to-Many doesn't work because I again have two keys, :from
and :to, that need to reference back.
For clarity, my models atm look like:
-------
class ContentType
include MongoMapper::Document
key :name, String
many :relationships
end
-------
class Relationship
include MongoMapper::Document
And I want to do:
r = Relationship.create
cfrom = ContentType.create
cto = ContentType.create
r.from = cfrom
r.to = cto
cfrom.relationships
or is this not the right data model with this db and the mongomapper
philosophy?
I could of cause just write custom modelfunctions to update the keys
in the inverse models.
I could save the Relationships embedded in both ContentTypes (I always
want to link 2 ContentTypes) but this also creates management
overhead.
Julian
On Feb 5, 12:03 am, John Nunemaker <nunema...@gmail.com> wrote:
> So the end goal is relating two content types to each other?
> On Sat, Feb 4, 2012 at 5:25 PM, juliangruber <misterio...@googlemail.com>wrote:
> > Hey,
> > I'm still new to mongo_wrapper so I hope my question isn't due to my
> > lack of knowledge.
> > I want to link two models in a way that I haven't seen examples of yet
> > with mongo_wrapper:
> > Model ContentType: name[String].
> > Model Relation: Each Relation has 2 ContentTypes referenced. rel.from
> > = [ContentType] rel.to = [ContentType]. Embedding is not an option
> > since each ContentType can belong to multiple relations.
> > So basically I have a [ContentType] N:N [Relation], [Relation] N:2
> > [ContentType] association model.
> > How can this be done? I tried in the Relation model:
> > one :content_type, :in => :from
> > one :from, :class_name => 'ContentType'
> > and other variations with :typecast eg.
> > Simply storing the respective _id's as ObjectId is no problem, but
> > then rel.from is just an id and I have to do the lookups myself via
> > ContentType.find(rel.from).
> > The only way I got this working is in the console with
> > c1 = ContentType.create
> > c2 = ContentType.create
> > c1.save!
> > c2.save!
> > rel = Relation.create
> > rel.from = c1
> > rel.to = c2
> > rel.save!
> > rel = Relationship.all.first => right ContentType
> > But then, rel doesn't save the _ids of the ContentTypes, rather the
> > _id of the Relation is saved in the content_types' relationship_id
> > field, which I don't find optimal and adds complexity to simple crud
> > operations.
> > Help is greatly appreciated, I hope my problem is clear.
> Yes, but the relation I aim for is not in the docs.
> One-to-Many doesn't work because I need 2 belongs_to statements in my > Relationship-Model > Many-to-Many doesn't work because I again have two keys, :from > and :to, that need to reference back.
> For clarity, my models atm look like:
> ------- > class ContentType > include MongoMapper::Document > key :name, String > many :relationships > end > ------- > class Relationship > include MongoMapper::Document
> And I want to do: > r = Relationship.create > cfrom = ContentType.create > cto = ContentType.create > r.from = cfrom > r.to = cto > cfrom.relationships
> or is this not the right data model with this db and the mongomapper > philosophy? > I could of cause just write custom modelfunctions to update the keys > in the inverse models.
> I could save the Relationships embedded in both ContentTypes (I always > want to link 2 ContentTypes) but this also creates management > overhead.
> Julian
> On Feb 5, 12:03 am, John Nunemaker <nunema...@gmail.com> wrote: > > So the end goal is relating two content types to each other?
> > On Sat, Feb 4, 2012 at 5:25 PM, juliangruber <misterio...@googlemail.com > >wrote:
> > > Hey,
> > > I'm still new to mongo_wrapper so I hope my question isn't due to my > > > lack of knowledge.
> > > I want to link two models in a way that I haven't seen examples of yet > > > with mongo_wrapper:
> > > Model ContentType: name[String]. > > > Model Relation: Each Relation has 2 ContentTypes referenced. rel.from > > > = [ContentType] rel.to = [ContentType]. Embedding is not an option > > > since each ContentType can belong to multiple relations.
> > > So basically I have a [ContentType] N:N [Relation], [Relation] N:2 > > > [ContentType] association model.
> > > How can this be done? I tried in the Relation model: > > > one :content_type, :in => :from > > > one :from, :class_name => 'ContentType' > > > and other variations with :typecast eg.
> > > Simply storing the respective _id's as ObjectId is no problem, but > > > then rel.from is just an id and I have to do the lookups myself via > > > ContentType.find(rel.from).
> > > The only way I got this working is in the console with > > > c1 = ContentType.create > > > c2 = ContentType.create > > > c1.save! > > > c2.save! > > > rel = Relation.create > > > rel.from = c1 > > > rel.to = c2 > > > rel.save! > > > rel = Relationship.all.first => right ContentType
> > > But then, rel doesn't save the _ids of the ContentTypes, rather the > > > _id of the Relation is saved in the content_types' relationship_id > > > field, which I don't find optimal and adds complexity to simple crud > > > operations.
> > > Help is greatly appreciated, I hope my problem is clear.
> > > -- Julian Gruber.
> > > -- > > > You received this message because you are subscribed to the Google > > > Groups "MongoMapper" group. > > > For more options, visit this group at > > >http://groups.google.com/group/mongomapper?hl=en?hl=en
> You want cfrom.relationships to check both the from and the to?
> On Sun, Feb 5, 2012 at 11:41 AM, juliangruber <misterio...@googlemail.com>wrote:
> > Yes, but the relation I aim for is not in the docs.
> > One-to-Many doesn't work because I need 2 belongs_to statements in my
> > Relationship-Model
> > Many-to-Many doesn't work because I again have two keys, :from
> > and :to, that need to reference back.
> > For clarity, my models atm look like:
> > -------
> > class ContentType
> > include MongoMapper::Document
> > key :name, String
> > many :relationships
> > end
> > -------
> > class Relationship
> > include MongoMapper::Document
> > And I want to do:
> > r = Relationship.create
> > cfrom = ContentType.create
> > cto = ContentType.create
> > r.from = cfrom
> > r.to = cto
> > cfrom.relationships
> > or is this not the right data model with this db and the mongomapper
> > philosophy?
> > I could of cause just write custom modelfunctions to update the keys
> > in the inverse models.
> > I could save the Relationships embedded in both ContentTypes (I always
> > want to link 2 ContentTypes) but this also creates management
> > overhead.
> > Julian
> > On Feb 5, 12:03 am, John Nunemaker <nunema...@gmail.com> wrote:
> > > So the end goal is relating two content types to each other?
> > > On Sat, Feb 4, 2012 at 5:25 PM, juliangruber <misterio...@googlemail.com
> > >wrote:
> > > > Hey,
> > > > I'm still new to mongo_wrapper so I hope my question isn't due to my
> > > > lack of knowledge.
> > > > I want to link two models in a way that I haven't seen examples of yet
> > > > with mongo_wrapper:
> > > > Model ContentType: name[String].
> > > > Model Relation: Each Relation has 2 ContentTypes referenced. rel.from
> > > > = [ContentType] rel.to = [ContentType]. Embedding is not an option
> > > > since each ContentType can belong to multiple relations.
> > > > So basically I have a [ContentType] N:N [Relation], [Relation] N:2
> > > > [ContentType] association model.
> > > > How can this be done? I tried in the Relation model:
> > > > one :content_type, :in => :from
> > > > one :from, :class_name => 'ContentType'
> > > > and other variations with :typecast eg.
> > > > Simply storing the respective _id's as ObjectId is no problem, but
> > > > then rel.from is just an id and I have to do the lookups myself via
> > > > ContentType.find(rel.from).
> > > > The only way I got this working is in the console with
> > > > c1 = ContentType.create
> > > > c2 = ContentType.create
> > > > c1.save!
> > > > c2.save!
> > > > rel = Relation.create
> > > > rel.from = c1
> > > > rel.to = c2
> > > > rel.save!
> > > > rel = Relationship.all.first => right ContentType
> > > > But then, rel doesn't save the _ids of the ContentTypes, rather the
> > > > _id of the Relation is saved in the content_types' relationship_id
> > > > field, which I don't find optimal and adds complexity to simple crud
> > > > operations.
> > > > Help is greatly appreciated, I hope my problem is clear.
> > > > -- Julian Gruber.
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups "MongoMapper" group.
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/mongomapper?hl=en?hl=en
I thought about this problem a bunch while working on MongoMapper's association documentation.
There's the supported Many-to-Many, which works find with objects of the same class:
class ContentType include MongoMapper::Document key :from_content_type_ids, Array, :typecast => 'ObjectId' many :from_content_types, :in => :from_content_type_ids
# sorry, no many-to-many inverse yet, our bad! def to_content_types ContentType.where(:from_content_type_ids => self.id) end
def related_content_types (from_content_types.to_a + to_content_types.to_a).uniq end end
You can also roll your own join table as two one-to-many relationships:
class Relationship include MongoMapper::Document key :from_content_type_id, ObjectId key :to_content_type_id, ObjectId belongs_to :from_content_type, :class_name => 'ContentType' belongs_to :to_content_type, :class_name => 'ContentType' end
class ContentType include MongoMapper::Document many :from_relationships, :class_name => 'Relationship', :foreign_key => :from_content_type_id many :to_relationships, :class_name => 'Relationship', :foreign_key => :to_content_type_id
def relationships from_relationships.to_a + to_relationships.to_a end
Or you can roll your relationship objects as embedded docs. You'd set it up like MongoMapper's standard Many-to-Many BUT instead of storing an array of id's you store an array of embedded documents. It would look like this (note that embedded docs always have their own id):
(Email the list again if you want to go this route and need code help...)
The advantage of embedded docs over MongoMapper's standard Many-to-Many is that you can add attributes to your relationship embedded documents to store more information about the relation, just like you can with ActiveRecord's many :through. For example, you could add a "related_at" timestamp to know when content types were linked up. BUT, if you don't need extra information about the relationship, you don't gain anything with embedded docs over MongoMapper's Many-to-Many.
Development wise, MM needs a Many-to-Many inverse first, then perhaps eager loading, and then maybe we can talk about "join tables" in Mongo. The embedded relationship documents approach is much more Mongo-y than a full out join collection. Embedded relationship document are the same number of queries as the current Many-to-Many implementation. A join collection requires an extra query because Mongo doesn't support joins. With the development pain to code it and maintain it, it might not be worth the gain. Does anyone else need join tables?
> Ideally cfrom would have an array with all ids...or else yes, check > from and to.
> However, I decided to go with embedded documents for relationships for > now, but still I think the original problem is worth solving isn't it?
> On Feb 6, 3:32 pm, John Nunemaker <nunema...@gmail.com> wrote: >> You want cfrom.relationships to check both the from and the to?
>> On Sun, Feb 5, 2012 at 11:41 AM, juliangruber <misterio...@googlemail.com>wrote:
>>> Yes, but the relation I aim for is not in the docs.
>>> One-to-Many doesn't work because I need 2 belongs_to statements in my >>> Relationship-Model >>> Many-to-Many doesn't work because I again have two keys, :from >>> and :to, that need to reference back.
>>> For clarity, my models atm look like:
>>> ------- >>> class ContentType >>> include MongoMapper::Document >>> key :name, String >>> many :relationships >>> end >>> ------- >>> class Relationship >>> include MongoMapper::Document
>>> And I want to do: >>> r = Relationship.create >>> cfrom = ContentType.create >>> cto = ContentType.create >>> r.from = cfrom >>> r.to = cto >>> cfrom.relationships
>>> or is this not the right data model with this db and the mongomapper >>> philosophy? >>> I could of cause just write custom modelfunctions to update the keys >>> in the inverse models.
>>> I could save the Relationships embedded in both ContentTypes (I always >>> want to link 2 ContentTypes) but this also creates management >>> overhead.
>>> Julian
>>> On Feb 5, 12:03 am, John Nunemaker <nunema...@gmail.com> wrote: >>>> So the end goal is relating two content types to each other?
>>>> On Sat, Feb 4, 2012 at 5:25 PM, juliangruber <misterio...@googlemail.com >>>> wrote:
>>>>> Hey,
>>>>> I'm still new to mongo_wrapper so I hope my question isn't due to my >>>>> lack of knowledge.
>>>>> I want to link two models in a way that I haven't seen examples of yet >>>>> with mongo_wrapper:
>>>>> Model ContentType: name[String]. >>>>> Model Relation: Each Relation has 2 ContentTypes referenced. rel.from >>>>> = [ContentType] rel.to = [ContentType]. Embedding is not an option >>>>> since each ContentType can belong to multiple relations.
>>>>> So basically I have a [ContentType] N:N [Relation], [Relation] N:2 >>>>> [ContentType] association model.
>>>>> How can this be done? I tried in the Relation model: >>>>> one :content_type, :in => :from >>>>> one :from, :class_name => 'ContentType' >>>>> and other variations with :typecast eg.
>>>>> Simply storing the respective _id's as ObjectId is no problem, but >>>>> then rel.from is just an id and I have to do the lookups myself via >>>>> ContentType.find(rel.from).
>>>>> The only way I got this working is in the console with >>>>> c1 = ContentType.create >>>>> c2 = ContentType.create >>>>> c1.save! >>>>> c2.save! >>>>> rel = Relation.create >>>>> rel.from = c1 >>>>> rel.to = c2 >>>>> rel.save! >>>>> rel = Relationship.all.first => right ContentType
>>>>> But then, rel doesn't save the _ids of the ContentTypes, rather the >>>>> _id of the Relation is saved in the content_types' relationship_id >>>>> field, which I don't find optimal and adds complexity to simple crud >>>>> operations.
>>>>> Help is greatly appreciated, I hope my problem is clear.
>>>>> -- Julian Gruber.
>>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "MongoMapper" group. >>>>> For more options, visit this group at >>>>> http://groups.google.com/group/mongomapper?hl=en?hl=en