You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2020/02/17 14:32:41 UTC
[couchdb] 01/22: add crude mango hook and indexer setup
This is an automated email from the ASF dual-hosted git repository.
garren pushed a commit to branch fdb-mango-indexes
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 38aa7c848bffd59a2cb8d61454f3be83b3a418ca
Author: Garren Smith <ga...@gmail.com>
AuthorDate: Tue Jan 21 13:39:56 2020 +0200
add crude mango hook and indexer setup
---
src/fabric/src/fabric2_fdb.erl | 13 ++--
src/mango/src/mango_fdb.erl | 35 ++++++++++
src/mango/src/mango_indexer.erl | 101 +++++++++++++++++++++++++++
src/mango/test/exunit/mango_indexer_test.exs | 68 ++++++++++++++++++
src/mango/test/exunit/test_helper.exs | 2 +
5 files changed, 215 insertions(+), 4 deletions(-)
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index e51b8de..33e3f97 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -761,13 +761,15 @@ write_doc(#{} = Db0, Doc, NewWinner0, OldWinner, ToUpdate, ToRemove) ->
if not IsDDoc -> ok; true ->
incr_stat(Db, <<"doc_design_count">>, 1)
end,
- incr_stat(Db, <<"doc_count">>, 1);
+ incr_stat(Db, <<"doc_count">>, 1),
+ mango_indexer:update(Db, created, Doc, not_found);
recreated ->
if not IsDDoc -> ok; true ->
incr_stat(Db, <<"doc_design_count">>, 1)
end,
incr_stat(Db, <<"doc_count">>, 1),
- incr_stat(Db, <<"doc_del_count">>, -1);
+ incr_stat(Db, <<"doc_del_count">>, -1),
+ mango_indexer:update(Db, created, Doc, not_found);
replicate_deleted ->
incr_stat(Db, <<"doc_del_count">>, 1);
ignore ->
@@ -777,9 +779,12 @@ write_doc(#{} = Db0, Doc, NewWinner0, OldWinner, ToUpdate, ToRemove) ->
incr_stat(Db, <<"doc_design_count">>, -1)
end,
incr_stat(Db, <<"doc_count">>, -1),
- incr_stat(Db, <<"doc_del_count">>, 1);
+ incr_stat(Db, <<"doc_del_count">>, 1),
+ OldDoc = get_doc_body(Db, DocId, OldWinner),
+ mango_indexer:update(Db, deleted, not_found, OldDoc);
updated ->
- ok
+ OldDoc = get_doc_body(Db, DocId, OldWinner),
+ mango_indexer:update(Db, updated, Doc, OldDoc)
end,
% Update database size
diff --git a/src/mango/src/mango_fdb.erl b/src/mango/src/mango_fdb.erl
new file mode 100644
index 0000000..c29ae8f
--- /dev/null
+++ b/src/mango/src/mango_fdb.erl
@@ -0,0 +1,35 @@
+% 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_fdb).
+
+
+-export([
+ write_doc/4
+]).
+
+
+write_doc(Db, Doc, Indexes, Results) ->
+ lists:foreach(fun (Index) ->
+ MangoIdxPrefix = mango_idx_prefix(Db, Index),
+ ok
+ end, Indexes).
+
+
+mango_idx_prefix(Db, Index) ->
+ #{
+ db_prefix := DbPrefix
+ } = Db,
+ io:format("INDEX ~p ~n", [Index]),
+ ok.
+
diff --git a/src/mango/src/mango_indexer.erl b/src/mango/src/mango_indexer.erl
new file mode 100644
index 0000000..b217ce1
--- /dev/null
+++ b/src/mango/src/mango_indexer.erl
@@ -0,0 +1,101 @@
+% 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_indexer).
+
+
+-export([
+ update/4
+]).
+
+
+update(Db, deleted, _, OldDoc) ->
+ ok;
+update(Db, updated, Doc, OldDoc) ->
+ ok;
+update(Db, created, Doc, _) ->
+%% Indexes = mango_idx:list(Db),
+%% Fun = fun (DDoc, Acc) ->
+%% io:format("DESIGN DOC ~p ~n", [DDoc]),
+%% Acc
+%% end,
+%% fabric2_db:fold_design_docs(Db, Fun, [], []),
+%% % maybe validate indexes here
+%% JSONDoc = mango_json:to_binary(couch_doc:to_json_obj(Doc, [])),
+%% io:format("Update ~p ~n, ~p ~n", [Doc, JSONDoc]),
+%% Results = index_doc(Indexes, JSONDoc),
+ ok.
+
+
+index_doc(Indexes, Doc) ->
+ lists:map(fun(Idx) -> get_index_entries(Idx, Doc) end, Indexes).
+
+
+get_index_entries({IdxProps}, Doc) ->
+ {Fields} = couch_util:get_value(<<"fields">>, IdxProps),
+ Selector = get_index_partial_filter_selector(IdxProps),
+ case should_index(Selector, Doc) of
+ false ->
+ [];
+ true ->
+ Values = get_index_values(Fields, Doc),
+ case lists:member(not_found, Values) of
+ true -> [];
+ false -> [[Values, null]]
+ end
+ end.
+
+
+get_index_values(Fields, Doc) ->
+ lists:map(fun({Field, _Dir}) ->
+ case mango_doc:get_field(Doc, Field) of
+ not_found -> not_found;
+ bad_path -> not_found;
+ Value -> Value
+ end
+ end, Fields).
+
+
+get_index_partial_filter_selector(IdxProps) ->
+ case couch_util:get_value(<<"partial_filter_selector">>, IdxProps, {[]}) of
+ {[]} ->
+ % this is to support legacy text indexes that had the partial_filter_selector
+ % set as selector
+ couch_util:get_value(<<"selector">>, IdxProps, {[]});
+ Else ->
+ Else
+ end.
+
+
+should_index(Selector, Doc) ->
+ NormSelector = mango_selector:normalize(Selector),
+ Matches = mango_selector:match(NormSelector, Doc),
+ IsDesign = case mango_doc:get_field(Doc, <<"_id">>) of
+ <<"_design/", _/binary>> -> true;
+ _ -> false
+ end,
+ Matches and not IsDesign.
+
+
+validate_index_info(IndexInfo) ->
+ IdxTypes = [mango_idx_view, mango_idx_text],
+ Results = lists:foldl(fun(IdxType, Results0) ->
+ try
+ IdxType:validate_index_def(IndexInfo),
+ [valid_index | Results0]
+ catch _:_ ->
+ [invalid_index | Results0]
+ end
+ end, [], IdxTypes),
+ lists:member(valid_index, Results).
+
diff --git a/src/mango/test/exunit/mango_indexer_test.exs b/src/mango/test/exunit/mango_indexer_test.exs
new file mode 100644
index 0000000..3a86ae4
--- /dev/null
+++ b/src/mango/test/exunit/mango_indexer_test.exs
@@ -0,0 +1,68 @@
+defmodule MangoIndexerTest do
+ use Couch.Test.ExUnit.Case
+
+ alias Couch.Test.Utils
+ alias Couch.Test.Setup
+ alias Couch.Test.Setup.Step
+
+ setup_all do
+ test_ctx =
+ :test_util.start_couch([:couch_log, :fabric, :couch_js, :couch_jobs])
+
+ on_exit(fn ->
+ :test_util.stop_couch(test_ctx)
+ end)
+ end
+
+ setup do
+ db_name = Utils.random_name("db")
+
+ admin_ctx =
+ {:user_ctx,
+ Utils.erlang_record(:user_ctx, "couch/include/couch_db.hrl", roles: ["_admin"])}
+
+ {:ok, db} = :fabric2_db.create(db_name, [admin_ctx])
+
+ docs = create_docs()
+ ddoc = create_ddoc()
+
+ {ok, _} = :fabric2_db.update_docs(db, [ddoc | docs])
+
+ on_exit(fn ->
+ :fabric2_db.delete(db_name, [admin_ctx])
+ end)
+
+ %{
+ :db_name => db_name,
+ :db => db,
+ :ddoc => ddoc
+ }
+ end
+
+ test "create design doc through _index", context do
+ db = context[:db]
+ end
+
+# Create 1 design doc that should be filtered out and ignored
+ defp create_ddocs() do
+ views = %{
+ "_id" => "_design/bar",
+ "views" => %{
+ "dates_sum" => %{
+ "map" => """
+ function(doc) {
+ if (doc.date) {
+ emit(doc.date, doc.date_val);
+ }
+ }
+ """
+ }
+ }
+ }
+ :couch_doc.from_json_obj(:jiffy.decode(:jiffy.encode(views)))
+ end
+
+ defp create_docs() do
+ []
+ end
+end
\ No newline at end of file
diff --git a/src/mango/test/exunit/test_helper.exs b/src/mango/test/exunit/test_helper.exs
new file mode 100644
index 0000000..f4ab64f
--- /dev/null
+++ b/src/mango/test/exunit/test_helper.exs
@@ -0,0 +1,2 @@
+ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
+ExUnit.start()
\ No newline at end of file