After exploring the source code a bit and abandoning a few other ways of 
achieving this, I've managed to get multi-key requests working. The only way to 
make it more efficient would require some digging into the couch_btree folding 
code, I think.

You use it by POSTing a JSON array of keys to a view url. Any passed-in values 
for start_key and end_key are ignored.

I haven't written any unittests for this yet, but I wanted to see what everyone 
else thinks of this and ask if there's any obvious better way to accomplish the 
same goal.

This patch is against the latest in SVN as of now. Any comments or suggestions 
for this are very much welcome.


Signed-off-by: Paul Bonser <[EMAIL PROTECTED]>
--

diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index af8d9b4..c813a4c 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -363,6 +363,37 @@ handle_db_request(Req, 'GET', {DbName, _Db, ["_view", 
DocId, ViewName]}) ->
         end
     end;
 
+% Multi-key request, with a JSON array of keys as the POST body
+handle_db_request(Req, 'POST', {DbName, _Db, ["_view", DocId, ViewName]}) ->
+    #view_query_args{
+        count = Count,
+        skip = SkipCount,
+        direction = Dir,
+        start_docid = StartDocId
+    } = QueryArgs = parse_view_query(Req),
+
+    case Req:get_primary_header_value("content-type") of
+        undefined -> ok;
+        "application/json" -> ok;
+        Else -> throw({incorrect_mime_type, Else})
+    end,
+       JsonKeys = tuple_to_list(cjson:decode(Req:recv_body())),
+
+    {ok, View} = couch_view:get_map_view({DbName, "_design/" ++ DocId, 
ViewName}),
+    {ok, RowCount} = couch_view:get_row_count(View),
+    FoldAccInit = {Count, SkipCount, undefined, []},
+    FoldResult = lists:foldl(fun(Key, {ok, FoldAcc}) ->
+        Start = {Key, StartDocId},
+        FoldlFun = make_view_fold_fun(Req, QueryArgs#view_query_args {
+                    start_key = Key,
+                    end_key = Key
+                }, 
+                RowCount, fun couch_view:reduce_to_count/1),
+        couch_view:fold(View, Start, Dir, FoldlFun, FoldAcc)
+    end, {ok, FoldAccInit}, JsonKeys),
+    finish_view_fold(Req, RowCount, FoldResult);
+
+
 handle_db_request(_Req, _Method, {_DbName, _Db, ["_view", _DocId, _ViewName]}) 
->
     throw({method_not_allowed, "GET,HEAD"});
 

Reply via email to