diff options
-rw-r--r-- | src/mango/src/mango_cursor_view.erl | 71 | ||||
-rw-r--r-- | src/mango/test/15-execution-stats-test.py | 4 |
2 files changed, 23 insertions, 52 deletions
diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index f5cd3822f..f1b753bd7 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -231,32 +231,26 @@ view_cb({row, Row}, #mrargs{extra = Options} = Acc) -> }, case ViewRow#view_row.doc of null -> - put(mango_docs_examined, get(mango_docs_examined) + 1), maybe_send_mango_ping(); undefined -> - ViewRow2 = ViewRow#view_row{ - value = couch_util:get_value(value, Row) - }, - ok = rexi:stream2(ViewRow2), - put(mango_docs_examined, 0), + % include_docs=false. Use quorum fetch at coordinator + ok = rexi:stream2(ViewRow), set_mango_msg_timestamp(); Doc -> + put(mango_docs_examined, get(mango_docs_examined) + 1), Selector = couch_util:get_value(selector, Options), case mango_selector:match(Selector, Doc) of true -> - ViewRow2 = ViewRow#view_row{ - value = get(mango_docs_examined) + 1 - }, - ok = rexi:stream2(ViewRow2), - put(mango_docs_examined, 0), + ok = rexi:stream2(ViewRow), set_mango_msg_timestamp(); false -> - put(mango_docs_examined, get(mango_docs_examined) + 1), maybe_send_mango_ping() end end, {ok, Acc}; view_cb(complete, Acc) -> + % Send shard-level execution stats + ok = rexi:stream2({execution_stats, {docs_examined, get(mango_docs_examined)}}), % Finish view output ok = rexi:stream_last(complete), {ok, Acc}; @@ -286,16 +280,16 @@ handle_message({meta, _}, Cursor) -> {ok, Cursor}; handle_message({row, Props}, Cursor) -> case doc_member(Cursor, Props) of - {ok, Doc, {execution_stats, ExecutionStats1}} -> + {ok, Doc, {execution_stats, Stats}} -> Cursor1 = Cursor#cursor { - execution_stats = ExecutionStats1 + execution_stats = Stats }, Cursor2 = update_bookmark_keys(Cursor1, Props), FinalDoc = mango_fields:extract(Doc, Cursor2#cursor.fields), handle_doc(Cursor2, FinalDoc); - {no_match, _, {execution_stats, ExecutionStats1}} -> + {no_match, _, {execution_stats, Stats}} -> Cursor1 = Cursor#cursor { - execution_stats = ExecutionStats1 + execution_stats = Stats }, {ok, Cursor1}; Error -> @@ -420,20 +414,14 @@ doc_member(Cursor, RowProps) -> Opts = Cursor#cursor.opts, ExecutionStats = Cursor#cursor.execution_stats, Selector = Cursor#cursor.selector, - {Matched, Incr} = case couch_util:get_value(value, RowProps) of - N when is_integer(N) -> {true, N}; - _ -> {false, 1} - end, case couch_util:get_value(doc, RowProps) of {DocProps} -> - ExecutionStats1 = mango_execution_stats:incr_docs_examined(ExecutionStats, Incr), - case Matched of - true -> - {ok, {DocProps}, {execution_stats, ExecutionStats1}}; - false -> - match_doc(Selector, {DocProps}, ExecutionStats1) - end; + % only matching documents are returned; the selector + % is evaluated at the shard level in view_cb({row, Row}, + {ok, {DocProps}, {execution_stats, ExecutionStats}}; undefined -> + % an undefined doc was returned, indicating we should + % perform a quorum fetch ExecutionStats1 = mango_execution_stats:incr_quorum_docs_examined(ExecutionStats), Id = couch_util:get_value(id, RowProps), case mango_util:defer(fabric, open_doc, [Db, Id, Opts]) of @@ -443,9 +431,9 @@ doc_member(Cursor, RowProps) -> Else -> Else end; - null -> - ExecutionStats1 = mango_execution_stats:incr_docs_examined(ExecutionStats), - {no_match, null, {execution_stats, ExecutionStats1}} + _ -> + % no doc, no match + {no_match, null, {execution_stats, ExecutionStats}} end. @@ -481,28 +469,8 @@ update_bookmark_keys(Cursor, _Props) -> -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -runs_match_on_doc_with_no_value_test() -> - Cursor = #cursor { - db = <<"db">>, - opts = [], - execution_stats = #execution_stats{}, - selector = mango_selector:normalize({[{<<"user_id">>, <<"1234">>}]}) - }, - RowProps = [ - {id,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, - {key,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, - {doc,{ - [ - {<<"_id">>,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, - {<<"_rev">>,<<"1-a954fe2308f14307756067b0e18c2968">>}, - {<<"user_id">>,11} - ] - }} - ], - {Match, _, _} = doc_member(Cursor, RowProps), - ?assertEqual(Match, no_match). -does_not_run_match_on_doc_with_value_test() -> +does_not_refetch_doc_with_value_test() -> Cursor = #cursor { db = <<"db">>, opts = [], @@ -512,7 +480,6 @@ does_not_run_match_on_doc_with_value_test() -> RowProps = [ {id,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, {key,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, - {value,1}, {doc,{ [ {<<"_id">>,<<"b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4">>}, diff --git a/src/mango/test/15-execution-stats-test.py b/src/mango/test/15-execution-stats-test.py index 922cadf83..d3687f8c8 100644 --- a/src/mango/test/15-execution-stats-test.py +++ b/src/mango/test/15-execution-stats-test.py @@ -53,6 +53,10 @@ class ExecutionStatsTests(mango.UserDocsTests): ) self.assertEqual(resp["execution_stats"]["results_returned"], len(resp["docs"])) + def test_no_matches_index_scan(self): + resp = self.db.find({"age": {"$lt": 35}, "nomatch": "me"}, return_raw=True, executionStats=True) + self.assertEqual(resp["execution_stats"]["total_docs_examined"], 3) + self.assertEqual(resp["execution_stats"]["results_returned"], 0) @unittest.skipUnless(mango.has_text_service(), "requires text service") class ExecutionStatsTests_Text(mango.UserDocsTextTests): |