You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2021/09/17 20:54:00 UTC

[couchdb] branch fix-descending-true-keys-view-query created (now 01c8977)

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a change to branch fix-descending-true-keys-view-query
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


      at 01c8977  Properly sort descending=true view results when a key list is provided

This branch includes the following new commits:

     new 01c8977  Properly sort descending=true view results when a key list is provided

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[couchdb] 01/01: Properly sort descending=true view results when a key list is provided

Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch fix-descending-true-keys-view-query
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 01c89770dc2fe7acff6ba6f64ed4abde4e5ad3ab
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Fri Sep 17 16:43:42 2021 -0400

    Properly sort descending=true view results when a key list is provided
    
    Results should now be returned in descending {key, doc_id} order.
    
    The idea is to reverse the key list before sending it to the workers, so they
    will emit rows in reverse order. Also, using the same reversed list when
    building the KeyDict structure on the coordinator. That way the order of the
    sent rows and the expected coordinator sorting order will match.
    
    For testing, enhance an existing multi-key Elixir view test to test both ascending
    and descending cases.
---
 src/fabric/src/fabric_view_map.erl              | 18 +++++++----
 test/elixir/test/view_multi_key_design_test.exs | 40 +++++++++++++++++++++----
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/src/fabric/src/fabric_view_map.erl b/src/fabric/src/fabric_view_map.erl
index ff6aa8b..8ab8083 100644
--- a/src/fabric/src/fabric_view_map.erl
+++ b/src/fabric/src/fabric_view_map.erl
@@ -24,8 +24,14 @@ go(DbName, Options, GroupId, View, Args, Callback, Acc, VInfo)
     {ok, DDoc} = fabric:open_doc(DbName, <<"_design/", GroupId/binary>>, []),
     go(DbName, Options, DDoc, View, Args, Callback, Acc, VInfo);
 
-go(Db, Options, DDoc, View, Args, Callback, Acc, VInfo) ->
+go(Db, Options, DDoc, View, Args0, Callback, Acc, VInfo) ->
     DbName = fabric:dbname(Db),
+    Args = case Args0 of
+        #mrargs{keys = Keys, direction = rev} when is_list(Keys) ->
+            Args0#mrargs{keys = lists:reverse(Keys)};
+        #mrargs{} ->
+            Args0
+    end,
     {Shards, RingOpts} = fabric_view:get_shards(Db, Args),
     {CoordArgs, WorkerArgs} = fabric_view:fix_skip_and_limit(Args),
     DocIdAndRev = fabric_util:doc_id_and_rev(DDoc),
@@ -221,10 +227,12 @@ merge_row(Dir, Collation, KeyDict0, Row, Rows0) ->
                             IdA < IdB;
                         {rev, 0} ->
                             IdB < IdA;
-                        {fwd, _} ->
-                            dict:fetch(A, KeyDict1) < dict:fetch(B, KeyDict1);
-                        {rev, _} ->
-                            dict:fetch(B, KeyDict1) < dict:fetch(A, KeyDict1)
+                        {_, _} ->
+                            % We already have a reversed key dict, and sent the
+                            % workers the same reversed keys list. So here we
+                            % just enforce sorting according to the order in
+                            % the key dict
+                            dict:fetch(A, KeyDict1) < dict:fetch(B, KeyDict1)
                     end
                 end,
                 [Row],
diff --git a/test/elixir/test/view_multi_key_design_test.exs b/test/elixir/test/view_multi_key_design_test.exs
index ab57e89..c334916 100644
--- a/test/elixir/test/view_multi_key_design_test.exs
+++ b/test/elixir/test/view_multi_key_design_test.exs
@@ -209,16 +209,38 @@ defmodule ViewMultiKeyDesignTest do
     assert length(rows) == 99
   end
 
-  test "dir works", context do
+  test "dir ascending works", context do
     db_name = context[:db_name]
 
-    resp = view(db_name, "test/multi_emit", [descending: true], [1])
+    expect_rows = mk_rows(0..99, 1, &</2) ++ mk_rows(0..99, 2, &</2)
+
+    resp = view(db_name, "test/multi_emit", [descending: false], [1, 2])
     rows = resp.body["rows"]
-    assert length(rows) == 100
+    assert length(rows) == 200
+    assert expect_rows == rows
 
-    resp = view(db_name, "test/multi_emit", descending: true, keys: :jiffy.encode([1]))
+    keys = :jiffy.encode([1, 2])
+    resp = view(db_name, "test/multi_emit", descending: false, keys: keys)
     rows = resp.body["rows"]
-    assert length(rows) == 100
+    assert length(rows) == 200
+    assert expect_rows == rows
+  end
+
+  test "dir descending works", context do
+    db_name = context[:db_name]
+
+    expect_rows = mk_rows(0..99, 2, &>/2) ++ mk_rows(0..99, 1, &>/2)
+
+    resp = view(db_name, "test/multi_emit", [descending: true], [1, 2])
+    rows = resp.body["rows"]
+    assert length(rows) == 200
+    assert expect_rows == rows
+
+    keys = :jiffy.encode([1, 2])
+    resp = view(db_name, "test/multi_emit", descending: true, keys: keys)
+    rows = resp.body["rows"]
+    assert length(rows) == 200
+    assert expect_rows == rows
   end
 
   test "argument combinations", context do
@@ -313,4 +335,12 @@ defmodule ViewMultiKeyDesignTest do
     rows = resp.body["rows"]
     assert length(rows) == 2
   end
+
+  defp mk_rows(range, key, sort_fun) do
+    row_fun = fn(i) -> %{"id" => "#{i}", "key" => key, "value" => i} end
+    sort_mapper = fn(row) -> {row["key"], row["id"]} end
+    range
+    |> Enum.map(row_fun)
+    |> Enum.sort_by(sort_mapper, sort_fun)
+  end
 end