couchdb icon indicating copy to clipboard operation
couchdb copied to clipboard

key vs endkey

Open ronag opened this issue 2 years ago • 7 comments

I believe that if key is provided, then endkey should be ignored? The docs seem to be unclear on this. However, the behavior I get is the opposite.

await couch.put('a', {})
await couch.put('b', {})
await couch.put('c', {})

const { rows } = await couch.allDocs({
  key: 'a',
  endkey: 'b'
})
console.log(rows)
test/index.js 2> [
test/index.js 2>   {
test/index.js 2>     id: 'a',
test/index.js 2>     key: 'a',
test/index.js 2>     value: { rev: '1-967a00dff5e02add41819138abb3284d' }
test/index.js 2>   },
test/index.js 2>   {
test/index.js 2>     id: 'b',
test/index.js 2>     key: 'b',
test/index.js 2>     value: { rev: '1-967a00dff5e02add41819138abb3284d' }
test/index.js 2>   }
test/index.js 2> ]

Looks like a bug?

couchdb:3.1.1

ronag avatar Mar 29 '22 04:03 ronag

@ronag thanks for your report.

key effectively behaves as if we are setting both startkey=$key&endkey=$key. So every time it is parsed it does exactly that.

However, we do have "keys" which returns an error as you mentioned:

http $DB/db/_all_docs'?keys=["c"]&endkey="b"'
HTTP/1.1 400 Bad Request
{
    "error": "query_parse_error",
    "reason": "`keys` is incompatible with `key`, `start_key` and `end_key`"
}

Perhaps key it should be translated to keys=[Key] internally, instead and behave similarly, but it maybe a compatibility issue in some cases as well. It could be a nice improvement for the future.

nickva avatar Mar 29 '22 19:03 nickva

@nickva What is the predence here though? It seems setting both key and endkey has different result that just setting key. Or does the order of the parameters matter?

ronag avatar Mar 30 '22 04:03 ronag

@ronag The precedence is in the order the parameters are specified. For example:

 http $DB/db/_all_docs'?endkey="b"&key="a"&key="c"'

Will set endkey to b then set both startkey and endkey to a then set both startkey and endkey to c and will emit c:

{
    "offset": 2,
    "rows": [
        {
            "id": "c",
            "key": "c",
            "value": {
                "rev": "1-935564bc7ec7e86aa82ecec3face18f6"
            }
        }
    ],
    "total_rows": 3
}

I can't think of any useful cases for this, but it has been like that for many years. It probably should be fixed to work like keys=[...] and raise a mutually_exclusive 400 error or some duplicate_parameter error and such as well.

I marked the issue as an enhancement. It could be picked up by a beginner contributor as it doesn't seem particularly difficult to implement. But, it might involve some discussion on the dev ML since it's a compatibility issue.

nickva avatar Mar 30 '22 15:03 nickva

Hi @ronag,

I would say that your example is working like expected, but you are right it seems a little bit confusing and needs an optimization in the future. You are accesing the _all_docs view endpoint and some view parameters are setting default values like inclusive_end, which is set to true.

So you would also get bin your result list. Maybe you can test it with ?inclusive_end=false and if bisn't in your result, then it is this default parameter...

big-r81 avatar Mar 31 '22 08:03 big-r81

The precedence is in the order the parameters are specifie

This answered my confusion.

ronag avatar Mar 31 '22 08:03 ronag

Does the beginner-friendly tag mean that this issue is good for new contributors?

abarbosa-godaddy avatar Sep 09 '22 12:09 abarbosa-godaddy

@abarbosa-godaddy yeah, that's the idea of the tag. To do some validation that some parameters are mutually exclusive.

nickva avatar Sep 10 '22 04:09 nickva