diff options
author | Garren Smith <garren.smith@gmail.com> | 2020-09-24 12:10:29 -0500 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2020-09-29 15:25:00 -0500 |
commit | 1460d4f035cddb7684c709e16aa8652e12ce6083 (patch) | |
tree | d748cd36877d194e4fd37db07934e8d3c2b52c22 | |
parent | 234a295c94992089916264909615e6e3109f4bda (diff) | |
download | couchdb-1460d4f035cddb7684c709e16aa8652e12ce6083.tar.gz |
Add elixir tests for builtin reduce group levels
-rw-r--r-- | test/elixir/test/reduce_builtin_group_level_tests.exs | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/test/elixir/test/reduce_builtin_group_level_tests.exs b/test/elixir/test/reduce_builtin_group_level_tests.exs new file mode 100644 index 000000000..2a183494e --- /dev/null +++ b/test/elixir/test/reduce_builtin_group_level_tests.exs @@ -0,0 +1,549 @@ +defmodule ReduceBuiltinGroupLevelTests do + use CouchTestCase + + setup do + db_name = random_db_name() + {:ok, _} = create_db(db_name) + on_exit(fn -> delete_db(db_name) end) + + docs = create_docs() + ddoc = create_ddoc() + + body = %{ + docs: [ddoc | docs] + } + + resp = Couch.post("/#{db_name}/_bulk_docs", body: body) + Enum.each(resp.body, &assert(&1["ok"])) + + %{ + :db_name => db_name, + :ddoc => ddoc + } + end + + test "group_level=0 reduce startkey/endkey", context do + args = %{ + reduce: true, + group_level: 0, + start_key: [2018, 3, 2], + end_key: [2019, 5, 1] + } + + correct = [ + %{"key" => :null, "value" => 31} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=0 reduce", context do + args = %{ + reduce: true, + group_level: 0 + } + + correct = [ + %{"key" => :null, "value" => 68} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce", context do + args = %{ + reduce: true, + group_level: 1 + } + + correct = [ + %{"key" => [2017], "value" => 31}, + %{"key" => [2018], "value" => 20}, + %{"key" => [2019], "value" => 17} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce with startkey/endkey", context do + args = %{ + reduce: true, + group_level: 1, + start_key: [2017, 4, 1], + end_key: [2018, 3, 1] + } + + correct = [ + %{"key" => [2017], "value" => 22}, + %{"key" => [2018], "value" => 6} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce with startkey/endkey take 2", context do + args = %{ + reduce: true, + group_level: 1, + start_key: [2017, 4, 1], + end_key: [2019, 3, 2] + } + + correct = [ + %{"key" => [2017], "value" => 22}, + %{"key" => [2018], "value" => 20}, + %{"key" => [2019], "value" => 4} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce with startkey/endkey take 3", context do + args = %{ + reduce: true, + group_level: 1, + start_key: [2017, 4, 1], + end_key: [2019, 05, 1] + } + + correct = [ + %{"key" => [2017], "value" => 22}, + %{"key" => [2018], "value" => 20}, + %{"key" => [2019], "value" => 17} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce with startkey", context do + args = %{ + reduce: true, + group_level: 1, + start_key: [2017, 4, 1] + } + + correct = [ + %{"key" => [2017], "value" => 22}, + %{"key" => [2018], "value" => 20}, + %{"key" => [2019], "value" => 17} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group_level=1 reduce with endkey", context do + args = %{ + reduce: true, + group_level: 1, + end_key: [2018, 5, 2] + } + + correct = [ + %{"key" => [2017], "value" => 31}, + %{"key" => [2018], "value" => 20} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "group=true reduce with startkey/endkey", context do + args = %{ + reduce: true, + group: true, + start_key: [2018, 5, 1], + end_key: [2019, 04, 1] + } + + correct = [ + %{"key" => [2018, 5, 1], "value" => 7}, + %{"key" => [2019, 3, 1], "value" => 4}, + %{"key" => [2019, 4, 1], "value" => 6} + ] + + run_query(context, args, "dates_sum", correct) + end + + test "mixed count reduce group_level=1", context do + args = %{ + reduce: true, + group_level: 1, + limit: 6 + } + + correct = [ + %{"key" => 1, "value" => 2}, + %{"key" => 2, "value" => 2}, + %{"key" => 3, "value" => 2}, + %{"key" => [1], "value" => 3}, + %{"key" => [2], "value" => 2}, + %{"key" => [3], "value" => 3} + ] + + run_query(context, args, "count", correct) + end + + test "mixed count reduce group_level=2", context do + args = %{ + :reduce => true, + :group_level => 2, + :limit => 9 + } + + correct = [ + %{"key" => 1, "value" => 2}, + %{"key" => 2, "value" => 2}, + %{"key" => 3, "value" => 2}, + %{"key" => [1, 1], "value" => 2}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [3, 1], "value" => 2}, + %{"key" => [3, 4], "value" => 1} + ] + + run_query(context, args, "count", correct) + end + + test "mixed _count reduce group=2 reduce with startkey/endkey", context do + args = %{ + reduce: true, + group_level: 2, + start_key: 3, + end_key: [3, 1] + } + + correct = [ + %{"key" => 3, "value" => 2}, + %{"key" => [1, 1], "value" => 2}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [3, 1], "value" => 1} + ] + + run_query(context, args, "count", correct) + end + + test "mixed _count reduce group=2 reduce with startkey/endkey direction = rev", + context do + args = %{ + reduce: true, + group_level: 2, + start_key: [3, 1], + end_key: [1, 1], + descending: true + } + + correct = [ + %{"key" => [3, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [1, 1], "value" => 2} + ] + + run_query(context, args, "count", correct) + + args1 = %{ + reduce: true, + group_level: 2, + start_key: [3, 1], + descending: true + } + + correct1 = [ + %{"key" => [3, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [1, 1], "value" => 2}, + %{"key" => 3, "value" => 2}, + %{"key" => 2, "value" => 2}, + %{"key" => 1, "value" => 2} + ] + + run_query(context, args1, "count", correct1) + + args2 = %{ + reduce: true, + group_level: 2, + end_key: [1, 1], + descending: true + } + + correct2 = [ + %{"key" => [3, 4], "value" => 1}, + %{"key" => [3, 1], "value" => 2}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [1, 1], "value" => 2} + ] + + run_query(context, args2, "count", correct2) + + args3 = %{ + reduce: true, + group_level: 0, + descending: true + } + + correct3 = [ + %{"key" => :null, "value" => 14} + ] + + run_query(context, args3, "count", correct3) + end + + test "mixed _count reduce group=2 reduce with skip", context do + args = %{ + reduce: true, + group_level: 2, + start_key: 3, + skip: 2, + end_key: [3, 1] + } + + correct = [ + %{"key" => [1, 2], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [3, 1], "value" => 1} + ] + + run_query(context, args, "count", correct) + end + + test "mixed _count reduce group=2 reduce inclusive_end = false", context do + args = %{ + reduce: true, + group_level: 2, + start_key: [1, 1], + end_key: [3, 1], + inclusive_end: false + } + + correct = [ + %{"key" => [1, 1], "value" => 2}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1} + ] + + run_query(context, args, "count", correct) + + end + + test "mixed _count reduce group=2 reduce inclusive_end = false descending", context do + + args1 = %{ + reduce: true, + group_level: 2, + start_key: [3, 1], + end_key: [1, 1], + descending: true, + inclusive_end: false + } + + correct1 = [ + %{"key" => [3, 1], "value" => 1}, + %{"key" => [2, 3], "value" => 1}, + %{"key" => [2, 1], "value" => 1}, + %{"key" => [1, 2], "value" => 1}, + %{"key" => [1, 1], "value" => 1} + ] + + run_query(context, args1, "count", correct1) + end + + test "strings count reduce group_level=1", context do + args = %{ + reduce: true, + group_level: 1, + start_key: "4" + } + + correct = [ + %{"key" => "5", "value" => 1}, + %{"key" => "6", "value" => 1}, + %{"key" => "7", "value" => 1}, + %{"key" => "8", "value" => 2}, + %{"key" => "9", "value" => 1} + ] + + run_query(context, args, "count_strings", correct) + end + + test "_stats reduce works", context do + args = %{ + reduce: true, + group_level: 1 + } + + correct = [ + %{ + "key" => [2017], + "value" => %{"sum" => 31, "count" => 4, "min" => 6, "max" => 9, "sumsqr" => 247} + }, + %{ + "key" => [2018], + "value" => %{"sum" => 20, "count" => 4, "min" => 3, "max" => 7, "sumsqr" => 110} + }, + %{ + "key" => [2019], + "value" => %{"sum" => 17, "count" => 3, "min" => 4, "max" => 7, "sumsqr" => 101} + } + ] + + run_query(context, args, "stats", correct) + end + + test "_approx_count_distinct reduce works", context do + args = %{ + reduce: true, + group_level: 1 + } + + correct = [ + %{"key" => [2017], "value" => 4}, + %{"key" => [2018], "value" => 3}, + %{"key" => [2019], "value" => 3} + ] + + run_query(context, args, "distinct", correct) + end + + test "get view info with reduce size", context do + db_name = context[:db_name] + + resp = Couch.post("/#{db_name}/_design/bar/_view/distinct/", body: %{reduce: true}) + assert resp.status_code == 200 + + resp = Couch.get("/#{db_name}/_design/bar/_info") + assert resp.status_code == 200 + assert resp.body["view_index"]["sizes"]["active"] == 1073 + end + + defp run_query(context, args, view, correct_resp) do + db_name = context[:db_name] + + resp = Couch.post("/#{db_name}/_design/bar/_view/#{view}/", body: args) + assert resp.status_code == 200 + rows = resp.body["rows"] + + assert(rows == correct_resp) + end + + defp create_docs() do + dates = [ + {[2017, 3, 1], 9}, + {[2017, 4, 1], 7}, + # out of order check + {[2019, 3, 1], 4}, + {[2017, 4, 15], 6}, + {[2018, 4, 1], 3}, + {[2017, 5, 1], 9}, + {[2018, 3, 1], 6}, + # duplicate check + {[2018, 4, 1], 4}, + {[2018, 5, 1], 7}, + {[2019, 4, 1], 6}, + {[2019, 5, 1], 7} + ] + + for i <- 1..11 do + group = + if rem(i, 3) == 0 do + "first" + else + "second" + end + + {date_key, date_val} = Enum.at(dates, i - 1) + + val = + if i == 4 do + 8 + else + i + end + + %{ + _id: "doc-id-#{i}", + value: i, + some: "field", + group: group, + date: date_key, + date_val: date_val, + random_val: val + } + end + end + + defp create_ddoc() do + %{ + "_id" => "_design/bar", + "views" => %{ + "dates_sum" => %{ + "map" => """ + + function(doc) { + emit(doc.date, doc.date_val); + } + """, + "reduce" => "_sum" + }, + "count_strings" => %{ + "map" => """ + function(doc) { + emit(doc.random_val.toString(), 1); + } + """, + "reduce" => "_count" + }, + "count" => %{ + "map" => """ + function(doc) { + if (doc.value > 3) { + return; + } + emit(doc.value, doc.value); + emit(doc.value, doc.value); + emit([doc.value, 1], doc.value); + emit([doc.value, doc.value + 1, doc.group.length], doc.value); + + if (doc.value === 3) { + emit([1, 1, 5], 1); + emit([doc.value, 1, 5], 1); + } + } + """, + "reduce" => "_count" + }, + "distinct" => %{ + "map" => """ + function(doc) { + emit(doc.date, doc.date_val); + } + """, + "reduce" => "_approx_count_distinct" + }, + "stats" => %{ + "map" => """ + function(doc) { + emit(doc.date, doc.date_val); + } + """, + "reduce" => "_stats" + }, + "no_reduce" => %{ + "map" => """ + function (doc) { + emit(doc._id, doc.value); + } + """ + } + } + } + end +end |