Asynchronous 如何在CouchDB中查询两种类型的记录

Asynchronous 如何在CouchDB中查询两种类型的记录,asynchronous,couchdb,pouchdb,nosql,Asynchronous,Couchdb,Pouchdb,Nosql,我在从数据库获取两种依赖类型的数据时遇到问题 我有一个我喜欢的汽车列表: localDB.query(function(doc) { if (doc.type === ‘list’) { emit(doc); } }, {include_docs : true}).then(function(response) { console.log(“cars”, response); // Save Cars List to app for(var i = 0; i <

我在从数据库获取两种依赖类型的数据时遇到问题

我有一个我喜欢的汽车列表:

localDB.query(function(doc) {
  if (doc.type === ‘list’) {
    emit(doc);
  }
}, {include_docs : true}).then(function(response) {
  console.log(“cars”, response);

  // Save Cars List to app
  for(var i = 0; i < response.rows.length; i++) {
    addToCarsList(response.rows[i].id, response.rows[i].carNumber);
  }
  console.log(“Cars List: " + carsListToString());

  return response;

}).then(function(listRecord) {

  listRecord.rows.forEach(function(element, index){

    console.log(index + ' -> ', element);

    localDB.query(function(doc) {
      console.log("filtering with carNb = " + element.carNb);
      if (doc.type === 'defect' && doc.listId == getCurrentListId() && doc.carNb == element.carNb ) {
        emit(doc);
      }
    }, {include_docs : false}).then(function(result){
      console.log("defects", result);

    }).catch(function(err){
      console.log("an error has occurred", err);
    });
  });

}).catch(function(err) {
  console.log('error', err);
});
localDB.query(函数(doc){
如果(doc.type==‘列表’){
发射(doc);
}
},{include_docs:true})。然后(函数(响应){
控制台日志(“汽车”,响应);
//将汽车列表保存到应用程序
对于(var i=0;i',元素);
localDB.query(函数(doc){
console.log(“使用carNb=“+element.carNb”进行过滤);
if(doc.type=='defect'&&doc.listId==getCurrentListId()&&doc.carNb==element.carNb){
发射(doc);
}
},{include_docs:false})。然后(函数(结果){
控制台日志(“缺陷”,结果);
}).catch(函数(err){
log(“发生错误”,err);
});
});
}).catch(函数(err){
console.log('error',err);
});
下面是发生的情况。在获得汽车列表后,我想查询每辆汽车的缺陷,然后将其存储在一些数组中。然后在所有查询完成后,我想用保存的数据构建UI

但实际情况是,forEach处理速度很快,并且不等待内部异步的localDb.query

如何根据父查询中的属性查询某些文档?我查看了PockDB文档中的承诺,但不知道如何执行


(请忘记卷曲的引号和可能出现的lint错误,此代码是手工匿名的,并且经过了超简化)

您正在寻找的方法是(执行所有承诺,完成后返回)

但是,您的查询已经非常低效。最好创建一个持久索引,否则它必须对每个
query()
(!)进行完整的数据库扫描。您可以继续阅读以了解详细信息

我建议安装,然后执行以下操作:

// helper method
function createDesignDoc(name, mapFunction) {
  var ddoc = {
    _id: '_design/' + name,
    views: {}
  };
  ddoc.views[name] = { map: mapFunction.toString() };
  return ddoc;
}

localDB.putIfNotExists(createDesignDoc('my_index', function (doc) {
  emit([doc.type, doc.listId, doc.carNb]);
})).then(function () {
  // find all docs with type 'list'
  return localDB.query('my_index', {
    startkey: ['list'],
    endkey: ['list', {}],
    include_docs: true
  });
}).then(function (response) {
  console.log("cars", response);

  // Save Cars List to app
  for(var i = 0; i < response.rows.length; i++) {
    addToCarsList(response.rows[i].id, response.rows[i].carNumber);
  }
  console.log("Cars List: " + carsListToString());

  return response;
}).then(function (listRecord) {

  return PouchDB.utils.Promise.all(listRecord.rows.map(function (row) {
    // find all docs with the given type, listId, carNb
    return localDB.query('my_index', {
      key: ['defect', getCurrentListId(), row.doc.carNb],
      include_docs: true
    });
  }));
}).then(function (finalResults) {
  console.log(finalResults);
}).catch(function(err){
  console.log("an error has occurred", err);
});
//helper方法
函数createDesignDoc(名称,映射函数){
var ddoc={
_id:“_design/”+名称,
视图:{}
};
ddoc.views[name]={map:mapFunction.toString()};
返回ddoc;
}
localDB.putIfNotExists(createDesignDoc('my_index',函数(doc)){
发出([doc.type,doc.listId,doc.carNb]);
})).然后(函数(){
//查找“列表”类型的所有文档
返回localDB.query('my_index'{
开始键:[“列表”],
endkey:['list',{}],
包含文档:true
});
}).然后(功能(响应){
控制台日志(“汽车”,响应);
//将汽车列表保存到应用程序
对于(var i=0;i
我在这里使用了一些技巧:

  • emit
    [doc.type,doc.listId,doc.carNb]
    ,允许我们按类型或按类型+listId+carNb进行查询
  • 当只查询类型时,我们可以执行
    {startkey:['list'],endkey:['list',{}]}
    ,它只匹配那些类型为“list”的,因为
    {}
    在CouchDB对象排序顺序中比字符串“高”
  • backdb.utils.Promise
    是一个“隐藏”的API,但是如果你问我的话,它使用起来非常安全。我们不太可能改变它

编辑另一个选项是使用新插件,该插件提供了一个简化的查询API,用于替换现有的map/reduce
query()
API。

您正在寻找的方法是(执行所有承诺,完成后返回)

但是,您的查询已经非常低效。最好创建一个持久索引,否则它必须对每个
query()
(!)进行完整的数据库扫描。您可以继续阅读以了解详细信息

我建议安装,然后执行以下操作:

// helper method
function createDesignDoc(name, mapFunction) {
  var ddoc = {
    _id: '_design/' + name,
    views: {}
  };
  ddoc.views[name] = { map: mapFunction.toString() };
  return ddoc;
}

localDB.putIfNotExists(createDesignDoc('my_index', function (doc) {
  emit([doc.type, doc.listId, doc.carNb]);
})).then(function () {
  // find all docs with type 'list'
  return localDB.query('my_index', {
    startkey: ['list'],
    endkey: ['list', {}],
    include_docs: true
  });
}).then(function (response) {
  console.log("cars", response);

  // Save Cars List to app
  for(var i = 0; i < response.rows.length; i++) {
    addToCarsList(response.rows[i].id, response.rows[i].carNumber);
  }
  console.log("Cars List: " + carsListToString());

  return response;
}).then(function (listRecord) {

  return PouchDB.utils.Promise.all(listRecord.rows.map(function (row) {
    // find all docs with the given type, listId, carNb
    return localDB.query('my_index', {
      key: ['defect', getCurrentListId(), row.doc.carNb],
      include_docs: true
    });
  }));
}).then(function (finalResults) {
  console.log(finalResults);
}).catch(function(err){
  console.log("an error has occurred", err);
});
//helper方法
函数createDesignDoc(名称,映射函数){
var ddoc={
_id:“_design/”+名称,
视图:{}
};
ddoc.views[name]={map:mapFunction.toString()};
返回ddoc;
}
localDB.putIfNotExists(createDesignDoc('my_index',函数(doc)){
发出([doc.type,doc.listId,doc.carNb]);
})).然后(函数(){
//查找“列表”类型的所有文档
返回localDB.query('my_index'{
开始键:[“列表”],
endkey:['list',{}],
包含文档:true
});
}).然后(功能(响应){
控制台日志(“汽车”,响应);
//将汽车列表保存到应用程序
对于(var i=0;i
我在这里使用了一些技巧:

  • emit
    [doc.type,doc.listId,doc.carNb]
    ,允许我们按类型或按类型+listId+carNb进行查询
  • 当只查询类型时,我们可以执行
    {startkey:['list'],endkey:['list',{}]}
    ,这只与类型“list”匹配
    // order documents results by list then defect
    var view = function (doc) {
      if (doc.type === 'list') {
        emit([doc._id, doc.carNumber, 1);
      } else if (doc.type === 'defect') {
        emit([doc.listId, doc.carNb, 2])
      }
    }
    
    localDB.query(view, { include_docs: true })
      .then(function(response) {
        return _(response.rows)
          .reduce(function(m, r) {
            if (r.key[2] === 1) {
              // initialize 
              r.doc.defects = [];
              m.push(r.doc)
              return m;
            }
            if (r.key[2] === 2) {
              var list = _(m).last()
              if (list._id === r.key[0] && list.carNumber === r.key[1]) {
                list.defects.push(r.doc);
              }
              return m;
            }
          }, []);  
      })
      .then(function(lists) {
        // bind to UI
      });