diff options
author | Will Holley <willholley@gmail.com> | 2017-12-19 13:04:44 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-19 13:04:44 +0000 |
commit | 7c37e5863905185902f2e07dc8ce0d3019df34e4 (patch) | |
tree | 2e5ce9556a9991d85d257391cf848c6386ad8a43 | |
parent | 8e0e8b3dda1b152589bd5b8909d3489d3b733b02 (diff) | |
download | couchdb-7c37e5863905185902f2e07dc8ce0d3019df34e4.tar.gz |
Mango: change catch-all field range priority (#1069)
01252f97 introduced a "catch-all" feature to Mango that allowed
queries to fall back on a full database scan (_all_docs) when
no valid index was available.
This worked by creating a special index range representing
the full database scan.
For example, a selector:
{ "_id": "foo" }
would be translated into a field range of:
[{ "startkey": "foo", "endkey": "foo"}]
then prepending the catch-all field range, we would have:
[
{ "startkey": null, "endkey": max_json_value},
{ "startkey": "foo", "endkey": "foo"}
]
This set gets passed into
mango_cursor_view:choose_best_index to determine most selective
index and field range combination to use. Unfortunately, in
the event that we have one possible index (all_docs) and multiple
valid ranges, it just chooses the first range it finds -
the full index scan in this case.
This commit makes the catch-all field range the last
available option, ensuring we use the more selective
range where available.
-rw-r--r-- | src/mango/src/mango_cursor_special.erl | 7 | ||||
-rw-r--r-- | src/mango/test/03-operator-test.py | 9 |
2 files changed, 13 insertions, 3 deletions
diff --git a/src/mango/src/mango_cursor_special.erl b/src/mango/src/mango_cursor_special.erl index 78cac7f5d..f4a760d1c 100644 --- a/src/mango/src/mango_cursor_special.erl +++ b/src/mango/src/mango_cursor_special.erl @@ -31,10 +31,13 @@ create(Db, Indexes, Selector, Opts) -> InitialRange = mango_idx_view:field_ranges(Selector), CatchAll = [{<<"_id">>, {'$gt', null, '$lt', mango_json_max}}], - FieldRanges = lists:append(CatchAll, InitialRange), + % order matters here - we only want to use the catchall index + % if no other range can fulfill the query (because we know) + % catchall is the most expensive range + FieldRanges = InitialRange ++ CatchAll, Composited = mango_cursor_view:composite_indexes(Indexes, FieldRanges), {Index, IndexRanges} = mango_cursor_view:choose_best_index(Db, Composited), - + Limit = couch_util:get_value(limit, Opts, mango_opts:default_limit()), Skip = couch_util:get_value(skip, Opts, 0), Fields = couch_util:get_value(fields, Opts, all_fields), diff --git a/src/mango/test/03-operator-test.py b/src/mango/test/03-operator-test.py index 239cc7d41..4650c7e84 100644 --- a/src/mango/test/03-operator-test.py +++ b/src/mango/test/03-operator-test.py @@ -264,6 +264,13 @@ class OperatorTextTests(mango.UserDocsTextTests, OperatorTests): class OperatorAllDocsTests(mango.UserDocsTestsNoIndexes, OperatorTests): - pass + def test_range_id_eq(self): + doc_id = "8e1c90c0-ac18-4832-8081-40d14325bde0" + r = self.db.find({ + "_id": doc_id + }, explain=True, return_raw=True) + + self.assertEqual(r["mrargs"]["end_key"], doc_id) + self.assertEqual(r["mrargs"]["start_key"], doc_id) |