使用PHP和MongoDB,我有一个名为users的集合,另一个名为同一个DB中的表单。
我使用Mongodb ObjectID作为表单集合中文档的用户标识符,将用户ObjectId保存为每个表单文档的uid。
我将在表单集合中创建一个uid字段的索引,但我的问题是我应该如何保存用户Objectid?
截至目前,我将其保存为普通字符串,如(简化)
$collection->insert( array('formName'=>'The name','uid'=>'CURRENT_USERS_ObjectId_AS_string') );
在这种情况下,这似乎是逻辑或最佳实践,为uid创建Mongodb ObjectID,如
$collection->insert( array('formName'=>'The name','uid'=> new MongoId('CURRENT_USERS_ObjectId_AS_string')) );
答案 0 :(得分:5)
manual references的使用非常好 - 甚至推荐使用。只有使用DbRefs才能提供特定的好处 - 例如允许自动取消引用(mongo脚本或php代码可以自动知道foo指向集合x,id y [在数据库z中])。
但是要避免类型杂耍。
在一个集合中实际拥有外键,并且它与集合的类型不同,它指向的是糟糕设计。类型杂耍是一般从发展中消除的东西,而不是介绍。
在db上运行的代码应该可以工作:
form = db.forms.findOne();
user = db.users.findOne({_id: form.user_id});
用户集合_id字段的类型无关紧要。使用问题中的模式,此代码变为:
form = db.forms.findOne();
user = db.users.findOne({_id: new MongoId(form.user_id)});
就其本身而言,这并不是一个巨大的差异,但它意味着您必须思考/记住转换这些引用,如果/当创建使用不同类型的集合时它会变得有问题 - 它会引入不一致。
请考虑以下事项:
> 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});
假设学校ID是唯一的代码。如果它不可能改变 - 使用_id字段是合适的,也是个好主意。现在,学校ID和用户ID是不同的类型:
> db.forms.findOne();
{
"_id" : ObjectId("508940370392baf87e68e31d"),
"user_id" : ObjectId("5089401c0392baf87e68e31b"),
"school_id" : 123
}
如果它们按原样存储,它仍然可能完全不知道查询中的这些不同类型:
form = db.forms.findOne();
school = db.schools.findOne({_id: form.school_id});
user = db.users.findOne({_id: form.user_id});
如果使用了不同的类型,则意味着有必要考虑“使用此集合我需要将字符串转换为ObjectId,但是使用此字符我必须不”。
这是一个本来可以避免的问题,而是 - 它被引入了。
答案 1 :(得分:4)
现在我不熟悉PHP,但你提出的架构设计很好。我在c#实现中使用了类似的结构。这里要清楚的是我的架构设计示例
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.
现在,如果我想查询任何用户的帐户,我可以使用用户类中的accountId查询它。
MongoDb将此引用技术称为手动引用,这也是它在此建议的链接http://docs.mongodb.org/manual/applications/database-references/