在couchdb中使用不同的键发出两次doc

时间:2013-07-01 07:04:41

标签: node.js view couchdb cradle

假设我有一个用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);
});

它运作得很好。我可以按idemail加载数据。但我不确定我是否应该这样做。

我有另一个解决方案,通过使用两个不同的视图保存相同的文档,例如byIdbyEmail,但是这样我保存了相同的文档两次,显然它会花费数据库的空间。

不确定哪种解决方案更好。

3 个答案:

答案 0 :(得分:5)

规范的解决方案是拥有两个视图,一个是电子邮件,一个是id。为了不浪费文档的空间,您只需将null作为值发出,然后在查询视图时使用include_docs=true查询参数。

此外,您可能希望使用_id代替id。这样,CouchDB确保ID是唯一的,您不必使用视图来循环文档。

答案 1 :(得分:1)

我将更改为两个单独的视图。这是明确和清楚的。当您在一个视图中两次发出相同的文档时 - 通过id和电子邮件,您可以有效地将2个视图合并为一个视图。您可以将其视为具有2个根分支的搜索树。我没有看到任何这样做的理由,并建议将数据访问和存储优化工作留给数据库。

视图组合也可能产生棘手的错误,当由于某种原因你混淆了id和电子邮件。

答案 2 :(得分:1)

使用不同的密钥多次发出同一文档绝对没有错。这是关于您的应用程序最有意义的内容。

如果idemail始终有效且可互换的方式来识别用户,那么单个视图就是完美的。例如,当id是某种唯一帐户引用时,允许用户使用该帐户或其(更难忘的)电子邮件地址登录。

但是,如果您需要区分这两个值,例如id仅适用于应用程序管理员,因此单独的视图可能更好。 (你可能会使用一个复杂的密钥......但这是另一个答案。)