使用手动参考非常好 - 甚至推荐。仅在DbRefs提供特定好处时才使用它们 - 例如允许自动取消引用(mongo 脚本或 php 代码可以自动知道 foo 指向集合 x,id y [in database z])。
不同的类型是一个糟糕的设计
但是避免类型杂耍。
在一个集合中拥有实际上是外键的东西,并且它与它所指向的集合的类型不同,这是一个糟糕的设计。一般来说,类型杂耍是从开发中消除的东西,而不是引入。
想想数据库
像这样在数据库上运行的代码应该可以工作:
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,但我不能使用这个”。
这是一个本可以避免的问题,但相反 - 它被引入了。