Couchdb 如何使用类似SQL的运算符查询数据库
由于对PouchDB/CouchDB相对较新,我仍在努力思考如何在不同情况下正确使用map/reduce 假设我有这样的文档结构:Couchdb 如何使用类似SQL的运算符查询数据库,couchdb,pouchdb,Couchdb,Pouchdb,由于对PouchDB/CouchDB相对较新,我仍在努力思考如何在不同情况下正确使用map/reduce 假设我有这样的文档结构: { _id: 'record/1', labels: { // many-to-many relationship 'label/1': true, // let's assume that this is 'Label A' 'label/3': true, // 'Label C' 'label/4': true // '
{
_id: 'record/1',
labels: {
// many-to-many relationship
'label/1': true, // let's assume that this is 'Label A'
'label/3': true, // 'Label C'
'label/4': true // 'Label D'
}
},
{
_id: 'record/2',
labels: {
'label/1': true, // 'Label A'
'label/2': true // 'Label B'
}
}
为db.query
函数定义视图的正确方法有哪些:
PockDB/CouchDB mapreduce查询中没有
或
操作,因此必须将其分解为两个单独的查询
最终,这些类型的操作将在中得到支持,但在撰写本文时,
$或
尚未实现。尽管我非常想使用PockDB find
插件,但我找不到实现所需功能的方法。相反,我使用了一种变通方法:
更改文档结构以在数组中存储标签ID
创建设计文档
它将为每个记录发出多个复杂键,以升序表示所有可能的标签映射。map
函数将利用递归过程生成密钥:
{
_id: '_design/records-with-labels',
views: {
'records-with-labels': {
map: function(doc) {
// important: sort them so that the required keys to be created are lesser
var labelIds = doc.labels.sort();
var lastIx = labelIds.length - 1;
var emitKey = function emitKey(currentKey, currentIx) {
console.log('emitting: ' + currentKey.join(',') + ' for ' + doc._id);
emit(currentKey, null);
var nextIx = currentIx + 1;
for (var jumpIx = nextIx + 1; jumpIx <= lastIx; jumpIx++) {
var jumpedLabelId = labelIds[jumpIx];
var jumpingKey = currentKey.concat([jumpedLabelId]);
console.log('emitting: ' + jumpingKey.join(',') + ' for ' + doc._id);
emit(jumpingKey, null);
}
if (nextIx > lastIx) {
return;
}
var nextLabelId = labelIds[nextIx];
currentKey.push(nextLabelId);
emitKey(currentKey, currentIx + 1);
};
labelIds.forEach(function(labelId, i) {
emitKey([labelId], i);
});
}.toString()
}
}
}
质疑
我只需要确保查询标签按升序排序
要查询具有“label/1”和“label/3”的记录,请执行以下操作:
Db.query('records-with-labels', {
key: ['label/1', 'label/3']
});
Db.query('records-with-labels', {
keys: [['label/1'], ['label/3']]
});
要查询具有“label/3”或“label/3”的记录,请执行以下操作:
Db.query('records-with-labels', {
key: ['label/1', 'label/3']
});
Db.query('records-with-labels', {
keys: [['label/1'], ['label/3']]
});
这将为我们提供具有两个标签的重复记录,但是reduce函数应该有助于消除它们
结论
现在我不知道是否有更好的解决方案,但这对我来说已经足够好了,因为在我的情况下,一个记录不会有太多的标签
如果您有更好的建议,请评论或编辑答案。这是一篇旧文章。但是,可以使用下划线.js来帮助处理某些查询。它可以帮助您提取所需的数据,而无需多次访问数据库(除非您愿意) 看一看。多个WHERE和OR子句的答案应该对你有帮助。这个插件看起来很有前途。虽然我不能在这个案例中使用它,但我希望在其他一些案例中使用它。