Hi,
I think this functionality would be hugely beneficial in CouchDB but
POST'ing to a view seems so very, very wrong to me.
How about using a GET on the view but support multiple 'key' args, one
for each of the view rows to return, e.g.
GET /somedb/_views/somedoc/someview?key=1&key=2&key=3
The 'key' arg(s) already seem to take precedence over startkey,
endkey, etc and the view always returns a 'rows' list so it /should/
be a matter of iterating the JSON values sent as 'key' instead of
parsing the JSON structure sent as POST content.
I guess there's the possibility of hitting max URL length problems on
some browsers/servers but that can be worked around by requesting the
view in batches of keys.
Thoughts?
- Matt
2008/7/23 Paul Bonser <[EMAIL PROTECTED]>:
> 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"});
>
>