如何使用类似SQL的运算符查询PouchDB [英] How to query PouchDB with SQL-like operators

查看:89
本文介绍了如何使用类似SQL的运算符查询PouchDB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相对于PouchDB / CouchDB来说,我还是比较陌生,我仍在努力思考如何在不同情况下正确使用map / reduce。



我有这样的文档结构:

  {
_id:'record / 1',
标签: {
//多对多关系
'label / 1':true,//假设这是'标签A'
'label / 3':true,// '标签C'
'标签/ 4':true //'标签D'
}
},
{
_id:'record / 2',
标签:{
'label / 1':true,//'标签A'
'label / 2':true //'标签B'
}
}

db.query定义视图的正确方法是什么?函数来搜索:


  1. 带有'Label A''Label B'

  2. 带有'Label A''Label B'


解决方案

尽可能多地使用 pouchdb-find 插件,我找不到实现所需功能的方法。相反,我使用了一种解决方法:



更改文档结构以将标签ID存储在数组中



  {_ id:'记录/ 1',名称:'记录1',标签:['label / 1','label / 2','label / 3']},
/ /可能在存储时未排序
{_id:'record / 2',名称:'Record 2',标签:['label / 1','label / 5','label / 7',' label / 3']},
{_id:'record / 3',名称:'Record 3',标签:['label / 2','label / 3','label / 4','label / 5']}



创建设计文档



它将为每个记录发出多个复杂键,以按升序表示所有可能的标签映射。 map 函数将利用递归过程来生成密钥:

  {
_id:'_design / records-with-labels',
视图:{
'records-with-labels':{
map:function(doc){
//重要:对它们进行排序,以便创建所需的键更少
var labelIds = doc.labels.sort();
var lastIx = labelIds.length-1;

var embedKey = function generateKey(currentKey,currentIx){
console.log(’missioning:‘+ currentKey.join(’,’)+’表示‘+ doc._id);
发射(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(发出: + jumpingKey.join(,)+代表 + doc._id);
发射(jumpingKey,null);
}

如果(nextIx> lastIx){
return;
}

var nextLabelId = labelIds [nextIx];

currentKey.push(nextLabelId);

发射关键字(currentKey,currentIx + 1);
};

labelIds.forEach(function(labelId,i){
glowKey([labelId],i);
});

} .toString()
}
}
}

例如,文档 record / 1 将生成以下键:

 发射:记录/ 1的标签/ 1 
发射:记录/ 1的标签/ 1,label / 3发射
发射:记录/的label / 1,label / 2 1
发射:label / 1,label / 2,label / 3用于记录/ 1
发射:label / 2用于记录/ 1
发射:label / 2,label / 3用于记录/ 1发射
:记录的标签/ 3/1



查询



我只需要确保查询标签按升序排序即可。



要查询具有 label / 1的记录'label / 3':

  Db.query('records-with-labels, {
键:['label / 1','label / 3']
});

查询具有'label / 3''label / 3':

  Db.query('records-with-labels',{
keys:[['label / 1'],['label / 3']]
});

这将为我们提供具有两个标签的重复记录,但reduce函数应有助于消除它们。 / p>

结论



目前我不知道是否有更好的解决方案,但这对于我,因为在我的情况下,记录不会有太多标签。



如果您有更好的建议,请评论或编辑答案。


Being relatively new to PouchDB/CouchDB, I'm still trying to wrap my head around how to use the map/reduce correctly in different cases.

Supposed that I have document structure like this:

{
  _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'
  }
}

What are the correct ways to define view for db.query function to search:

  1. records with 'Label A' or 'Label B'
  2. records with 'Label A' and 'Label B'

解决方案

As much as I wanted to use the pouchdb-find plugin, I couldn't find a way to achieve what I needed. Instead I used a workaround:

Change the document structure to store label IDs in an array

{_id: 'record/1', name: 'Record 1', labels: ['label/1', 'label/2', 'label/3']},
// may not be sorted when being stored
{_id: 'record/2', name: 'Record 2', labels: ['label/1', 'label/5', 'label/7', 'label/3']},
{_id: 'record/3', name: 'Record 3', labels: ['label/2', 'label/3', 'label/4', 'label/5']}

Create a design document

It will emit multiple complex keys for each record to represent all possible label-mappings in an ascending order. The map function will utilize a recursive process to generate the keys:

{
  _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()
    }
  }
}

For example, the document record/1 will have these keys generated:

emitting: label/1 for record/1
emitting: label/1,label/3 for record/1
emitting: label/1,label/2 for record/1
emitting: label/1,label/2,label/3 for record/1
emitting: label/2 for record/1
emitting: label/2,label/3 for record/1
emitting: label/3 for record/1

Querying

I just need to ensure that the query labels are sorted in ascending order.

To query records that have 'label/1' and 'label/3':

Db.query('records-with-labels', {
  key: ['label/1', 'label/3']
});

To query records that have 'label/3' or 'label/3':

Db.query('records-with-labels', {
  keys: [['label/1'], ['label/3']]
});

This will give us duplicated records that has both labels, but a reduce function should help eliminating them.

Conclusion

For now I don't know if there is a better solution, but this is good enough for me because in my case, a record will not have too many labels.

If you have better suggestions, please comment or edit the answer.

这篇关于如何使用类似SQL的运算符查询PouchDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆