Couchdb 如何同时使用范围约束一个关键点,并使用精确匹配约束另一个关键点?

Couchdb 如何同时使用范围约束一个关键点,并使用精确匹配约束另一个关键点?,couchdb,couchdb-nano,Couchdb,Couchdb Nano,我创建了一个test Node.js脚本,它使用Nano生成一些示例数据文档,创建两个视图,并运行两个测试查询。每个数据文档有两个键:a和b。我希望我的查询结果是a在1到3之间,b等于2的所有文档。我测试了一个在线发现的视图/查询模式,该模式使用startkey数组和endkey数组。但是,在约束b之前约束a时,它的行为与预期的不一样,但在约束a之前约束b时,它的行为似乎与预期的一样 为什么b_then_a视图看起来有效,而a_then_b视图无效?这种做法是否错误?下面是脚本及其输出 var

我创建了一个test Node.js脚本,它使用Nano生成一些示例数据文档,创建两个视图,并运行两个测试查询。每个数据文档有两个键:a和b。我希望我的查询结果是a在1到3之间,b等于2的所有文档。我测试了一个在线发现的视图/查询模式,该模式使用startkey数组和endkey数组。但是,在约束b之前约束a时,它的行为与预期的不一样,但在约束a之前约束b时,它的行为似乎与预期的一样

为什么b_then_a视图看起来有效,而a_then_b视图无效?这种做法是否错误?下面是脚本及其输出

var nano = require("nano")("http://HCOADAMM:HcoAdammRSM@localhost:5984");

let jasonDB = nano.db.use("jason");

const DESIGN_DOCUMENT_NAME = "findtest";

var testData = [
    { a: 1, b: 1 },
    { a: 1, b: 2 },
    { a: 1, b: 3 },
    { a: 1, b: 4 },
    { a: 2, b: 1 },
    { a: 2, b: 2 },
    { a: 2, b: 3 },
    { a: 2, b: 4 },
    { a: 3, b: 1 },
    { a: 3, b: 2 },
    { a: 3, b: 3 },
    { a: 3, b: 4 },
    { a: 4, b: 1 },
    { a: 4, b: 2 },
    { a: 4, b: 3 },
    { a: 4, b: 4 }
];


var shuffleArray = function(arrayIn) {
    var arrayInLength = arrayIn.length;
    var arrayOut = [];
    while(arrayInLength)
        arrayOut.push(arrayIn.splice(
            parseInt(Math.random() * (arrayInLength--)), 1
        )[0]);
    return arrayOut;
}

var createTestRecords = function() {

    var recordsShuffled = shuffleArray(testData);

    recordsShuffled.forEach(function(record) {
        jasonDB.insert(
            record,
            function(err, body) {
                if(err)
                    console.log(err);
                else
                    console.log("updated user doc " + JSON.stringify(body));
            }
        );    
    });
}

var createDesignDocument = function() {

    jasonDB.get("_design/" + DESIGN_DOCUMENT_NAME, {}, function(err, body, headers) {
        if(!err || err.error === "not_found") {

            var dbObject = new Object();
            dbObject._id = "_design/" + DESIGN_DOCUMENT_NAME;
            if(!err) {
                dbObject._rev = body._rev;
            }
            dbObject.language = "javascript";

            dbObject.views = {
                a_then_b: {
                    map: function(doc) {
                        emit([doc.a, doc.b]);
                    }
                },
                b_then_a: {
                    map: function(doc) {
                        emit([doc.b, doc.a]);
                    }
                },
            };

            jasonDB.insert(dbObject, function(err, body, header) {
                if(err) {
                    console.log("insert error:");
                    console.log(err);
                } else {
                    console.log("created " + "jason/_design/" + DESIGN_DOCUMENT_NAME);
                }
            })
        } else {
            console.log("get error:");
            console.log(err);
        }
    });


}

var queryTest = function() {

    jasonDB.view(
        DESIGN_DOCUMENT_NAME,
        "a_then_b",
        { startkey: [1, 2], endkey: [3, 2] },
        function(err, body) {
            if(err) {
                console.log(err);
            } else {
                console.log("a_then_b")
                body.rows.forEach(function(el) {
                    console.log(el);
                });
                console.log("body.rows.length = " + body.rows.length);
                console.log("");
            }
        }
    );

    jasonDB.view(
        DESIGN_DOCUMENT_NAME,
        "b_then_a",
        { startkey: [2, 1], endkey: [2, 3] },
        function(err, body) {
            if(err) {
                console.log(err);
            } else {
                console.log("b_then_a")
                body.rows.forEach(function(el) {
                    console.log(el);
                });
                console.log("body.rows.length = " + body.rows.length);
            }
        }
    );
}

//createTestRecords();
//createDesignDocument();
setTimeout(function() {
    queryTest();
}, 1000);
输出:


只有当第二个键是索引中的第一个键时,才能执行此操作。因此,您需要在索引中对键进行排序,以便首先对b进行索引,然后对a进行索引。这将允许您在[2,1]到[2,3]的范围内进行搜索。

这在官方文档中有描述吗?视图和索引的功能有很好的文档记录。同样的逻辑也适用于Mango查询,虽然没有很好的文档记录,但您可以开始。简而言之:索引只能使用单个范围。但您的查询很容易适应单个范围。
a_then_b
{ id: '812f16b3826569ec94eb35d087030d64',
  key: [ 1, 2 ],
  value: null }
{ id: '812f16b3826569ec94eb35d087030709',
  key: [ 1, 3 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702a846',
  key: [ 1, 4 ],
  value: null }
{ id: '812f16b3826569ec94eb35d087032077',
  key: [ 2, 1 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702fd89',
  key: [ 2, 2 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702caee',
  key: [ 2, 3 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702c32a',
  key: [ 2, 4 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702b358',
  key: [ 3, 1 ],
  value: null }
{ id: '812f16b3826569ec94eb35d087031386',
  key: [ 3, 2 ],
  value: null }
body.rows.length = 9

b_then_a
{ id: '812f16b3826569ec94eb35d087030d64',
  key: [ 2, 1 ],
  value: null }
{ id: '812f16b3826569ec94eb35d08702fd89',
  key: [ 2, 2 ],
  value: null }
{ id: '812f16b3826569ec94eb35d087031386',
  key: [ 2, 3 ],
  value: null }
body.rows.length = 3