blob: 67bc7afc1f08e51f01f6941a99f15eae62b2d9ca [file] [log] [blame]
%%
%% 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.
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
-module(nouveau_bookmark).
-include_lib("mem3/include/mem3.hrl").
-export([new/0, update/3, unpack/2, pack/1, to_ejson/1]).
new() ->
#{}.
%% Form a bookmark from the last contribution from each shard range
update(DbName, PreviousBookmark, SearchResults) when is_binary(PreviousBookmark) ->
update(DbName, unpack(DbName, PreviousBookmark), SearchResults);
update(DbName, {EJson}, SearchResults) when is_list(EJson) ->
update(DbName, from_ejson({EJson}), SearchResults);
update(DbName, PreviousBookmark, SearchResults) when is_map(PreviousBookmark) ->
#{<<"hits">> := Hits} = SearchResults,
NewBookmark0 = lists:foldl(
fun(#{<<"id">> := Id, <<"order">> := Order}, Acc) ->
Acc#{range_of(DbName, Id) => Order}
end,
new(),
Hits
),
maps:merge(PreviousBookmark, NewBookmark0).
range_of(DbName, DocId) when is_binary(DbName), is_binary(DocId) ->
[#shard{range = Range} | _] = mem3_shards:for_docid(DbName, DocId),
Range;
range_of(DbName, Order) when is_binary(DbName), is_list(Order) ->
#{<<"@type">> := <<"string">>, <<"value">> := DocId} = lists:last(Order),
range_of(DbName, DocId).
unpack(_DbName, Empty) when Empty == undefined; Empty == nil; Empty == null ->
new();
unpack(DbName, PackedBookmark) when is_list(PackedBookmark) ->
unpack(DbName, list_to_binary(PackedBookmark));
unpack(DbName, PackedBookmark) when is_binary(PackedBookmark) ->
Bookmark = jiffy:decode(base64:decode(PackedBookmark), [return_maps]),
maps:from_list([{range_of(DbName, V), V} || V <- Bookmark]).
pack(nil) ->
null;
pack({EJson}) when is_list(EJson) ->
pack(from_ejson(EJson));
pack(UnpackedBookmark) when is_map(UnpackedBookmark) ->
Values = maps:values(UnpackedBookmark),
Encoded = jiffy:encode(Values),
Compressed = zlib:compress(Encoded),
base64:encode(Compressed).
%% legacy use of ejson within mango
from_ejson({Props}) ->
maps:from_list(Props).
to_ejson(Bookmark) when is_map(Bookmark) ->
{maps:to_list(Bookmark)}.