如何使用pouchdb创建动态查询(couchdb可能是同一件事)?

时间:2015-03-31 13:37:41

标签: javascript couchdb pouchdb

我有一个动态查询,我想用PouchDB编写,但我发现很难翻译我使用SQL数据库与PouchDB相比如何实现这一点。

我在PouchDB中有许多类型为'session'的文档,需要对这种类型的文档进行复杂的搜索。我想过滤标题(以提供的价值开头的字符串),状态,所有者,设备ID,开始日期,结束日期和其他一些事情。

现在,我知道我可以发出一个数组键,如:

            document.views = {
                by_title_status_owner: {
                    map: function(document) {
                        if(document._id.startsWith('session')) {
                            emit([
                                document.title.toUpperCase(),
                                document.status.text.toUpperCase(),
                                document.owner.refId
                            ], null);
                        }
                    }.toString()
                }
            };

我的问题是我不知道如何使用startkeyendkey进行查询。我正在尝试这样的事情:

                startkey: [
                    (filters.title || '').toUpperCase(),
                    (filters.status || '').toUpperCase(),
                    (filters.owner || '')
                ],
                endkey: [
                    (filters.title || '').toUpperCase() + '\uffff',
                    (filters.status || '').toUpperCase() + '\uffff',
                    (filters.owner || '').toUpperCase() + '\uffff'
                ],

但它似乎只是过滤了第一个索引 - 这意味着它正确地过滤了标题,但是当按状态或所有者搜索时,查询会返回所有结果。

我认为问题在于我真的想提供不同的发射数组键,并根据用户输入的内容提供不同的startkey / endkey组合,但这对PouchDB来说似乎很难。

例如,假设用户为其title搜索键入了“Lig”,并选择CLOSED作为状态。这意味着startkey应该看起来像['LIG','CLOSED'],而endkey可能看起来像['LIG \ uffff','CLOSED']。但这是否意味着我必须发出每个键索引的排列以匹配这个动态启动键/结束键?

这是我第一次尝试这个,我甚至没有添加2+参数emited键.....

        getAllByCriteria: function(filters) {
            var startkey = [], endkey = [];

            if(filters.title) {
                startkey.push((filters.title || '').toUpperCase());
                endkey.push((filters.title || '').toUpperCase() + '\uffff');
            }

            if(filters.status) {
                startkey.push((filters.status).toUpperCase());
                endkey.push((filters.status).toUpperCase());
            }

            if(filters.owner) {
                startkey.push(filters.owner);
                endkey.push(filters.owner);
            }

            return Database.instance().query('session_indexes/by_criteria', {
                startkey: startkey,
                endkey: endkey,
                include_docs: true
            }).then(function(result) {
                return _(result.rows).map(function(row) {
                    return Session.fromDocument(row.doc, new Session());
                });
            });
        },

        db.upsert('_design/session_indexes', function(document) {
            document.views = {
                by_criteria: {
                    map: function(document) {
                        if(document._id.startsWith('session')) {
                            emit([], null)
                            emit([document.title.toUpperCase()], null);
                            emit([document.status.text.toUpperCase()], null);
                            emit([document.owner.refId], null);
                        }
                    }.toString()
                }
            };

            return document;
        });

我真的很困惑。我很感激任何帮助。

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用视图和列表的组合。

  1. 使用地图fn发出["title", doc.title.toUpperCase()]["status", doc.status.toUpperCase()]等密钥,说indexfn

  2. 创建_list fn,说filter接受{field1:"value1", field2:"value2"...}之类的查询 - 列表可以接收自定义查询参数,而不像地图fns。如果行不匹配,则必须删除行。当然要使过滤成为可能,你的_list必须从视图fn接收完整(或某种方式修剪)的字段集。

  3. 执行/_design/ddoc/_list/filter/_view/indexfn?startkey=["field1","val1"] & endkey=["field1","val1z"] & filter={"field2":"val2", "field3":"val3"}

  4. 等请求

    当你的_list从视图中收到不超过一千行时,这种方法是合理的 - 从视图到_lists fn到最终用户的管道数据安静得很慢。

    因此,如果你有或多或少的alphbetically分布数据集与〜1M记录,如果你发送3或更多字符长的startkey,你可以有良好的性能。