You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2015/02/03 16:13:48 UTC
[41/50] [abbrv] couchdb-mango git commit: Implement the use_index
query parameter
Implement the use_index query parameter
This adds the ability for users to specify a specific index to use when
responding to a query. There are a few places where its helpful to force
the index selection to a specific index. For instance choosing a more
sparse single column index over an available multi-column index.
BugzId: 33294
Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/1b0426aa
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/1b0426aa
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/1b0426aa
Branch: refs/heads/master
Commit: 1b0426aa2839f34d747e329ffb8bbaee1c42aaa8
Parents: 812cf6b
Author: Paul J. Davis <pa...@gmail.com>
Authored: Fri Jan 9 15:32:40 2015 -0600
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Fri Jan 16 13:32:50 2015 -0600
----------------------------------------------------------------------
src/mango_cursor.erl | 35 ++++++++++++++++++++++++++++++++++-
src/mango_opts.erl | 33 +++++++++++++++++++++++++++++++++
test/05-index-selection-test.py | 34 ++++++++++++++++++++++++++++++++++
test/mango.py | 3 ++-
4 files changed, 103 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1b0426aa/src/mango_cursor.erl
----------------------------------------------------------------------
diff --git a/src/mango_cursor.erl b/src/mango_cursor.erl
index d4d5523..72ee8bb 100644
--- a/src/mango_cursor.erl
+++ b/src/mango_cursor.erl
@@ -36,7 +36,12 @@ create(Db, Selector0, Opts) ->
?MANGO_ERROR({no_usable_index, no_indexes_defined})
end,
- SortIndexes = mango_idx:for_sort(ExistingIndexes, Opts),
+ FilteredIndexes = maybe_filter_indexes(ExistingIndexes, Opts),
+ if FilteredIndexes /= [] -> ok; true ->
+ ?MANGO_ERROR({no_usable_index, no_index_matching_name})
+ end,
+
+ SortIndexes = mango_idx:for_sort(FilteredIndexes, Opts),
if SortIndexes /= [] -> ok; true ->
?MANGO_ERROR({no_usable_index, missing_sort_index})
end,
@@ -77,6 +82,34 @@ execute(#cursor{index=Idx}=Cursor, UserFun, UserAcc) ->
Mod:execute(Cursor, UserFun, UserAcc).
+maybe_filter_indexes(Indexes, Opts) ->
+ case lists:keyfind(use_index, 1, Opts) of
+ {use_index, []} ->
+ Indexes;
+ {use_index, [DesignId]} ->
+ filter_indexes(Indexes, DesignId);
+ {use_index, [DesignId, ViewName]} ->
+ filter_indexes(Indexes, DesignId, ViewName)
+ end.
+
+
+filter_indexes(Indexes, DesignId0) ->
+ DesignId = case DesignId0 of
+ <<"_design/", _/binary>> ->
+ DesignId0;
+ Else ->
+ <<"_design/", Else/binary>>
+ end,
+ FiltFun = fun(I) -> mango_idx:ddoc(I) == DesignId end,
+ lists:filter(FiltFun, Indexes).
+
+
+filter_indexes(Indexes0, DesignId, ViewName) ->
+ Indexes = filter_indexes(Indexes0, DesignId),
+ FiltFun = fun(I) -> mango_idx:name(I) == ViewName end,
+ lists:filter(FiltFun, Indexes).
+
+
create_cursor(Db, Indexes, Selector, Opts) ->
[{CursorMod, CursorModIndexes} | _] = group_indexes_by_type(Indexes),
CursorMod:create(Db, CursorModIndexes, Selector, Opts).
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1b0426aa/src/mango_opts.erl
----------------------------------------------------------------------
diff --git a/src/mango_opts.erl b/src/mango_opts.erl
index 43c2f31..e15a446 100644
--- a/src/mango_opts.erl
+++ b/src/mango_opts.erl
@@ -28,6 +28,7 @@
validate_idx_name/1,
validate_selector/1,
+ validate_use_index/1,
validate_sort/1,
validate_fields/1
]).
@@ -75,6 +76,12 @@ validate_find({Props}) ->
{tag, selector},
{validator, fun validate_selector/1}
]},
+ {<<"use_index">>, [
+ {tag, use_index},
+ {optional, true},
+ {default, []},
+ {validator, fun validate_use_index/1}
+ ]},
{<<"limit">>, [
{tag, limit},
{optional, true},
@@ -178,6 +185,32 @@ validate_selector(Else) ->
?MANGO_ERROR({invalid_selector_json, Else}).
+validate_use_index(IndexName) when is_binary(IndexName) ->
+ case binary:split(IndexName, <<"/">>) of
+ [DesignId] ->
+ {ok, [DesignId]};
+ [<<"_design">>, DesignId] ->
+ {ok, [DesignId]};
+ [DesignId, ViewName] ->
+ {ok, [DesignId, ViewName]};
+ [<<"_design">>, DesignId, ViewName] ->
+ {ok, [DesignId, ViewName]};
+ _ ->
+ ?MANGO_ERROR({invalid_index_name, IndexName})
+ end;
+validate_use_index(null) ->
+ {ok, []};
+validate_use_index([]) ->
+ {ok, []};
+validate_use_index([DesignId]) when is_binary(DesignId) ->
+ {ok, [DesignId]};
+validate_use_index([DesignId, ViewName])
+ when is_binary(DesignId), is_binary(ViewName) ->
+ {ok, [DesignId, ViewName]};
+validate_use_index(Else) ->
+ ?MANGO_ERROR({invalid_index_name, Else}).
+
+
validate_sort(Value) ->
mango_sort:new(Value).
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1b0426aa/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
new file mode 100644
index 0000000..5aa86c6
--- /dev/null
+++ b/test/05-index-selection-test.py
@@ -0,0 +1,34 @@
+
+import mango
+import user_docs
+
+
+class IndexSelectionTests(mango.UserDocsTests):
+
+ def test_basic(self):
+ resp = self.db.find({"name.last": "A last name"}, explain=True)
+ assert resp["index"]["type"] == "json"
+
+ def test_with_and(self):
+ resp = self.db.find({
+ "name.first": "Stephanie",
+ "name.last": "This doesn't have to match anything."
+ }, explain=True)
+ assert resp["index"]["type"] == "json"
+
+ def test_use_most_columns(self):
+ # ddoc id for the age index
+ ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f"
+ resp = self.db.find({
+ "name.first": "Stephanie",
+ "name.last": "Something or other",
+ "age": {"$gt": 1}
+ }, explain=True)
+ assert resp["index"]["ddoc"] != "_design/" + ddocid
+
+ resp = self.db.find({
+ "name.first": "Stephanie",
+ "name.last": "Something or other",
+ "age": {"$gt": 1}
+ }, use_index=ddocid, explain=True)
+ assert resp["index"]["ddoc"] == ddocid
http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/1b0426aa/test/mango.py
----------------------------------------------------------------------
diff --git a/test/mango.py b/test/mango.py
index fac4e7e..5b022b8 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -107,9 +107,10 @@ class Database(object):
r.raise_for_status()
def find(self, selector, limit=25, skip=0, sort=None, fields=None,
- r=1, conflicts=False, explain=False):
+ r=1, conflicts=False, explain=False, use_index=None):
body = {
"selector": selector,
+ "use_index": use_index,
"limit": limit,
"skip": skip,
"r": r,