summaryrefslogtreecommitdiff
path: root/src/mango/src/mango_cursor_text.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mango/src/mango_cursor_text.erl')
-rw-r--r--src/mango/src/mango_cursor_text.erl343
1 files changed, 0 insertions, 343 deletions
diff --git a/src/mango/src/mango_cursor_text.erl b/src/mango/src/mango_cursor_text.erl
deleted file mode 100644
index 5989f342e..000000000
--- a/src/mango/src/mango_cursor_text.erl
+++ /dev/null
@@ -1,343 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(mango_cursor_text).
-
--ifdef(HAVE_DREYFUS).
-
--export([
- create/4,
- explain/1,
- execute/3
-]).
-
-
--include_lib("couch/include/couch_db.hrl").
--include_lib("dreyfus/include/dreyfus.hrl").
--include("mango_cursor.hrl").
--include("mango.hrl").
-
-
--record(cacc, {
- selector,
- dbname,
- ddocid,
- idx_name,
- query_args,
- bookmark,
- limit,
- skip,
- user_fun,
- user_acc,
- fields,
- execution_stats
-}).
-
-
-create(Db, Indexes, Selector, Opts) ->
- Index = case Indexes of
- [Index0] ->
- Index0;
- _ ->
- ?MANGO_ERROR(multiple_text_indexes)
- end,
-
- Bookmark = unpack_bookmark(couch_db:name(Db), Opts),
-
- DreyfusLimit = get_dreyfus_limit(),
- Limit = erlang:min(DreyfusLimit, 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),
-
- {ok, #cursor{
- db = Db,
- index = Index,
- ranges = null,
- selector = Selector,
- opts = Opts,
- limit = Limit,
- skip = Skip,
- fields = Fields,
- bookmark = Bookmark
- }}.
-
-
-explain(Cursor) ->
- #cursor{
- selector = Selector,
- opts = Opts
- } = Cursor,
- [
- {'query', mango_selector_text:convert(Selector)},
- {partition, get_partition(Opts, null)},
- {sort, sort_query(Opts, Selector)}
- ].
-
-
-execute(Cursor, UserFun, UserAcc) ->
- #cursor{
- db = Db,
- index = Idx,
- limit = Limit,
- skip = Skip,
- selector = Selector,
- opts = Opts,
- execution_stats = Stats,
- bookmark = Bookmark
- } = Cursor,
- Query = mango_selector_text:convert(Selector),
- QueryArgs = #index_query_args{
- q = Query,
- partition = get_partition(Opts, nil),
- sort = sort_query(Opts, Selector),
- raw_bookmark = true
- },
- CAcc = #cacc{
- selector = Selector,
- dbname = couch_db:name(Db),
- ddocid = ddocid(Idx),
- idx_name = mango_idx:name(Idx),
- bookmark = Bookmark,
- limit = Limit,
- skip = Skip,
- query_args = QueryArgs,
- user_fun = UserFun,
- user_acc = UserAcc,
- fields = Cursor#cursor.fields,
- execution_stats = mango_execution_stats:log_start(Stats)
- },
- try
- case Query of
- <<>> ->
- throw({stop, CAcc});
- _ ->
- execute(CAcc)
- end
- catch
- throw:{stop, FinalCAcc} ->
- #cacc{
- bookmark = FinalBM,
- user_fun = UserFun,
- user_acc = LastUserAcc,
- execution_stats = Stats0
- } = FinalCAcc,
- JsonBM = dreyfus_bookmark:pack(FinalBM),
- Arg = {add_key, bookmark, JsonBM},
- {_Go, FinalUserAcc} = UserFun(Arg, LastUserAcc),
- FinalUserAcc0 = mango_execution_stats:maybe_add_stats(Opts, UserFun, Stats0, FinalUserAcc),
- FinalUserAcc1 = mango_cursor:maybe_add_warning(UserFun, Cursor, Stats0, FinalUserAcc0),
- {ok, FinalUserAcc1}
- end.
-
-
-execute(CAcc) ->
- case search_docs(CAcc) of
- {ok, Bookmark, []} ->
- % If we don't have any results from the
- % query it means the request has paged through
- % all possible results and the request is over.
- NewCAcc = CAcc#cacc{bookmark = Bookmark},
- throw({stop, NewCAcc});
- {ok, Bookmark, Hits} ->
- NewCAcc = CAcc#cacc{bookmark = Bookmark},
- HitDocs = get_json_docs(CAcc#cacc.dbname, Hits),
- {ok, FinalCAcc} = handle_hits(NewCAcc, HitDocs),
- execute(FinalCAcc)
- end.
-
-
-search_docs(CAcc) ->
- #cacc{
- dbname = DbName,
- ddocid = DDocId,
- idx_name = IdxName
- } = CAcc,
- QueryArgs = update_query_args(CAcc),
- case dreyfus_fabric_search:go(DbName, DDocId, IdxName, QueryArgs) of
- {ok, Bookmark, _, Hits, _, _} ->
- {ok, Bookmark, Hits};
- {error, Reason} ->
- ?MANGO_ERROR({text_search_error, {error, Reason}})
- end.
-
-
-handle_hits(CAcc, []) ->
- {ok, CAcc};
-
-handle_hits(CAcc0, [{Sort, Doc} | Rest]) ->
- CAcc1 = handle_hit(CAcc0, Sort, Doc),
- handle_hits(CAcc1, Rest).
-
-
-handle_hit(CAcc0, Sort, not_found) ->
- CAcc1 = update_bookmark(CAcc0, Sort),
- CAcc1;
-
-handle_hit(CAcc0, Sort, Doc) ->
- #cacc{
- limit = Limit,
- skip = Skip,
- execution_stats = Stats
- } = CAcc0,
- CAcc1 = update_bookmark(CAcc0, Sort),
- Stats1 = mango_execution_stats:incr_docs_examined(Stats),
- couch_stats:increment_counter([mango, docs_examined]),
- CAcc2 = CAcc1#cacc{execution_stats = Stats1},
- case mango_selector:match(CAcc2#cacc.selector, Doc) of
- true when Skip > 0 ->
- CAcc2#cacc{skip = Skip - 1};
- true when Limit == 0 ->
- % We hit this case if the user spcified with a
- % zero limit. Notice that in this case we need
- % to return the bookmark from before this match
- throw({stop, CAcc0});
- true when Limit == 1 ->
- NewCAcc = apply_user_fun(CAcc2, Doc),
- throw({stop, NewCAcc});
- true when Limit > 1 ->
- NewCAcc = apply_user_fun(CAcc2, Doc),
- NewCAcc#cacc{limit = Limit - 1};
- false ->
- CAcc2
- end.
-
-
-apply_user_fun(CAcc, Doc) ->
- FinalDoc = mango_fields:extract(Doc, CAcc#cacc.fields),
- #cacc{
- user_fun = UserFun,
- user_acc = UserAcc,
- execution_stats = Stats
- } = CAcc,
- Stats0 = mango_execution_stats:incr_results_returned(Stats),
- case UserFun({row, FinalDoc}, UserAcc) of
- {ok, NewUserAcc} ->
- CAcc#cacc{user_acc = NewUserAcc, execution_stats = Stats0};
- {stop, NewUserAcc} ->
- throw({stop, CAcc#cacc{user_acc = NewUserAcc, execution_stats = Stats0}})
- end.
-
-
-%% Convert Query to Dreyfus sort specifications
-%% Covert <<"Field">>, <<"desc">> to <<"-Field">>
-%% and append to the dreyfus query
-sort_query(Opts, Selector) ->
- {sort, {Sort}} = lists:keyfind(sort, 1, Opts),
- SortList = lists:map(fun(SortField) ->
- {Dir, RawSortField} = case SortField of
- {Field, <<"asc">>} -> {asc, Field};
- {Field, <<"desc">>} -> {desc, Field};
- Field when is_binary(Field) -> {asc, Field}
- end,
- SField = mango_selector_text:append_sort_type(RawSortField, Selector),
- case Dir of
- asc ->
- SField;
- desc ->
- <<"-", SField/binary>>
- end
- end, Sort),
- case SortList of
- [] -> relevance;
- _ -> SortList
- end.
-
-
-get_partition(Opts, Default) ->
- case couch_util:get_value(partition, Opts) of
- <<>> -> Default;
- Else -> Else
- end.
-
-
-get_bookmark(Opts) ->
- case lists:keyfind(bookmark, 1, Opts) of
- {_, BM} when is_list(BM), BM /= [] ->
- BM;
- _ ->
- nil
- end.
-
-
-update_bookmark(CAcc, Sortable) ->
- BM = CAcc#cacc.bookmark,
- QueryArgs = CAcc#cacc.query_args,
- Sort = QueryArgs#index_query_args.sort,
- NewBM = dreyfus_bookmark:update(Sort, BM, [Sortable]),
- CAcc#cacc{bookmark = NewBM}.
-
-
-pack_bookmark(Bookmark) ->
- case dreyfus_bookmark:pack(Bookmark) of
- null -> nil;
- Enc -> Enc
- end.
-
-
-unpack_bookmark(DbName, Opts) ->
- case lists:keyfind(bookmark, 1, Opts) of
- {_, nil} ->
- [];
- {_, Bin} ->
- try
- dreyfus_bookmark:unpack(DbName, Bin)
- catch _:_ ->
- ?MANGO_ERROR({invalid_bookmark, Bin})
- end
- end.
-
-
-ddocid(Idx) ->
- case mango_idx:ddoc(Idx) of
- <<"_design/", Rest/binary>> ->
- Rest;
- Else ->
- Else
- end.
-
-
-update_query_args(CAcc) ->
- #cacc{
- bookmark = Bookmark,
- query_args = QueryArgs
- } = CAcc,
- QueryArgs#index_query_args{
- bookmark = pack_bookmark(Bookmark),
- limit = get_limit(CAcc)
- }.
-
-
-get_limit(CAcc) ->
- erlang:min(get_dreyfus_limit(), CAcc#cacc.limit + CAcc#cacc.skip).
-
-
-get_dreyfus_limit() ->
- config:get_integer("dreyfus", "max_limit", 200).
-
-
-get_json_docs(DbName, Hits) ->
- Ids = lists:map(fun(#sortable{item = Item}) ->
- couch_util:get_value(<<"_id">>, Item#hit.fields)
- end, Hits),
- % TODO: respect R query parameter (same as json indexes)
- {ok, IdDocs} = dreyfus_fabric:get_json_docs(DbName, Ids),
- lists:map(fun(#sortable{item = Item} = Sort) ->
- Id = couch_util:get_value(<<"_id">>, Item#hit.fields),
- case lists:keyfind(Id, 1, IdDocs) of
- {Id, {doc, Doc}} ->
- {Sort, Doc};
- false ->
- {Sort, not_found}
- end
- end, Hits).
-
--endif.