couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Matt Goodall" <matt.good...@gmail.com>
Subject Re: [PATCH] Views: Multiple keys
Date Wed, 23 Jul 2008 12:58:36 GMT
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 <misterpib@gmail.com>:
> 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 <misterpib@gmail.com>
> --
>
> 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"});
>
>

Mime
View raw message