Couchdb 如何使用类似SQL的运算符查询数据库

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 // '

由于对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 // 'Label D'
  }
},
{
  _id: 'record/2',
  labels: {
    'label/1': true, // 'Label A'
    'label/2': true // 'Label B'
  }
}
db.query
函数定义视图的正确方法有哪些:

  • 带有“标签A”或“标签B”的记录
  • 带有“标签A”和“标签B”的记录

  • 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子句的答案应该对你有帮助。这个插件看起来很有前途。虽然我不能在这个案例中使用它,但我希望在其他一些案例中使用它。