如何使用类似SQL的运算符查询PouchDB [英] How to query PouchDB with SQL-like operators
问题描述
相对于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定义视图的正确方法是什么?
函数来搜索:
- 带有'Label A'或'Label B'
- 带有'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:
- records with 'Label A' or 'Label B'
- 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屋!