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"});