summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Holley <willholley@gmail.com>2017-12-19 13:04:44 +0000
committerGitHub <noreply@github.com>2017-12-19 13:04:44 +0000
commit7c37e5863905185902f2e07dc8ce0d3019df34e4 (patch)
tree2e5ce9556a9991d85d257391cf848c6386ad8a43
parent8e0e8b3dda1b152589bd5b8909d3489d3b733b02 (diff)
downloadcouchdb-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.erl7
-rw-r--r--src/mango/test/03-operator-test.py9
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)