Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB, Using Mongodb ObjectID between collections

Tags:

php

mongodb

Using PHP and MongoDB, i have a collection called users and another one called forms in the same DB.

I am using the Mongodb ObjectID as user identifier for the documents in the forms collection, saving the users ObjectId as uid on each forms document.

I am going to create an index of the uid field in the forms collection, but my question is how i should save the users Objectid?

As of now I am saving it as a normal string like (simplified)

$collection->insert( array('formName'=>'The name','uid'=>'CURRENT_USERS_ObjectId_AS_string') );

Does this seem logic or is best practice in this case to create a Mongodb ObjectID for uid like

$collection->insert( array('formName'=>'The name','uid'=> new MongoId('CURRENT_USERS_ObjectId_AS_string')) );
like image 506
Henkealg Avatar asked Dec 27 '22 15:12

Henkealg


2 Answers

The use of manual references is perfectly fine - recommended even. Only use DbRefs if they offer specific benefits - such as permitting automatic de-referencing (a mongo script or php code can automatically know that foo points at collection x, with id y [in database z]).

Different types is a bad design

However avoid type juggling.

Having what is effectively a foreign key in one collection, and it being a different type from that of the collection it's pointing at is a bad design. Type juggling is something to eliminate from development in general, not introduce.

Think about the database

Code like this ran on the db should work:

form = db.forms.findOne();
user = db.users.findOne({_id: form.user_id});

And it shouldn't matter what type the users collection _id field is. With the schema in the question this code becomes:

form = db.forms.findOne();
user = db.users.findOne({_id: new MongoId(form.user_id)});

In and of itself, that's not a huge difference, but it means you have to think/remember to convert these references and it becomes problematic if/when a collection is created which uses a different type - it introduces inconsistencies.

Consider the following:

> school = db.schools.insert({_id: 123, name: "my school"});
> userId = new ObjectId();
> db.users.insert({_id: userId, name: "Me"});
> db.forms.insert({user_id: userId, school_id: 123});

Let's say that the school id is a unique code. if there's no possibility it could change - it's appropriate and a good idea to use as the _id field. Now, the school id and the user id are different types:

> db.forms.findOne();
{
"_id" : ObjectId("508940370392baf87e68e31d"),
"user_id" : ObjectId("5089401c0392baf87e68e31b"),
"school_id" : 123
}

If they are stored as-is, it's still possible to be completely ignorant of these different types in queries:

form = db.forms.findOne();
school = db.schools.findOne({_id: form.school_id});
user = db.users.findOne({_id: form.user_id});

If different types are used that means that it becomes necessary to think "with this collection I need to convert the string to an ObjectId, but with this one I must not".

That's a problem that could have been avoided, but instead - it was introduced.

like image 199
AD7six Avatar answered Dec 29 '22 05:12

AD7six


Now I am not familiar with PHP but the schema design that you have suggested is good.I am using a similar structure for my c# implementation.Just to be clear here is a sample of my schema design

Account Class

public  ObjectId Id{get;set;}
public   string  Email {get;set}
public   string  Password{get;set;}

User Class

 public ObjectId Id{get;set;} 
 public string  AccountId {get;set}//refers to the ID in the account.

Now if I want to query an account for any user I can simply query it using the accountId in the user class.

MongoDb calls this referencing technique as manual referencing and this is also the one that it recommends here is the link http://docs.mongodb.org/manual/applications/database-references/

like image 33
Akshat Jiwan Sharma Avatar answered Dec 29 '22 05:12

Akshat Jiwan Sharma