假设我有一个用couchDB保存的文档,文档看起来像这样:
{
"email": "lorem@gmail.com",
"name": "lorem",
"id": "lorem",
"password": "sha1$bc5c595c$1$d0e9fa434048a5ae1dfd23ea470ef2bb83628ed6"
}
我希望能够通过'id'或'email'查询文档。因此,当我将其保存为视图时,我会这样写:
db.save('_design/users', {
byId: {
map: function(doc) {
if (doc.id && doc.email) {
emit(doc.id, doc);
emit(doc.email, doc);
}
}
}
});
然后我可以这样查询:
db.view('users/byId', {
key: key
}, function(err, data) {
if (err || data.length === 0) return def.reject(new Error('not found'));
data = data[0] || {};
data = data.value || {};
self.attrs = _.clone(data);
delete self.attrs._rev;
delete self.attrs._id;
def.resolve(data);
});
它运作得很好。我可以按id
或email
加载数据。但我不确定我是否应该这样做。
我有另一个解决方案,通过使用两个不同的视图保存相同的文档,例如byId
和byEmail
,但是这样我保存了相同的文档两次,显然它会花费数据库的空间。
不确定哪种解决方案更好。
答案 0 :(得分:5)
规范的解决方案是拥有两个视图,一个是电子邮件,一个是id。为了不浪费文档的空间,您只需将null作为值发出,然后在查询视图时使用include_docs=true
查询参数。
此外,您可能希望使用_id
代替id
。这样,CouchDB确保ID是唯一的,您不必使用视图来循环文档。
答案 1 :(得分:1)
我将更改为两个单独的视图。这是明确和清楚的。当您在一个视图中两次发出相同的文档时 - 通过id和电子邮件,您可以有效地将2个视图合并为一个视图。您可以将其视为具有2个根分支的搜索树。我没有看到任何这样做的理由,并建议将数据访问和存储优化工作留给数据库。
视图组合也可能产生棘手的错误,当由于某种原因你混淆了id和电子邮件。
答案 2 :(得分:1)
使用不同的密钥多次发出同一文档绝对没有错。这是关于您的应用程序最有意义的内容。
如果id
和email
始终有效且可互换的方式来识别用户,那么单个视图就是完美的。例如,当id
是某种唯一帐户引用时,允许用户使用该帐户或其(更难忘的)电子邮件地址登录。
但是,如果您需要区分这两个值,例如id
仅适用于应用程序管理员,因此单独的视图可能更好。 (你可能会使用一个复杂的密钥......但这是另一个答案。)