Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

filter fields in included doc when returned from a _changes

With this changes you can only return a specified list of fields in the
included docs by passing the list of them to an optionnal `fields`
parameter. For now nested fields are ignored.

    $ curl -XPUT localhost:5984/testdb
    {"ok":true}
    $ curl -XPUT localhost:5984/testdb/test -d'{"f1": 1, "f2": 2, "f3":
3}'
    {"ok":true,"id":"test","rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478"}
    $ curl -XPUT localhost:5984/testdb/test1 -d'{"f1": 1, "f2": 4, "f3":
3}'
    {"ok":true,"id":"test1","rev":"1-2942771a428c4b45315710db0b6aaa7a"}
    $ curl -XPUT localhost:5984/testdb/test2 -d'{"f1": 1, "f2": 7, "f3":
8}'
    {"ok":true,"id":"test2","rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3"}
    $ curl "http://localhost:5984/testdb/_changes?include_docs=true"
    {"results":[
    {"seq":1,"id":"test","changes":[{"rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478"}],"doc":{"_id":"test","_rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478","f1":1,"f2":2,"f3":3}},
    {"seq":2,"id":"test1","changes":[{"rev":"1-2942771a428c4b45315710db0b6aaa7a"}],"doc":{"_id":"test1","_rev":"1-2942771a428c4b45315710db0b6aaa7a","f1":1,"f2":4,"f3":3}},
    {"seq":3,"id":"test2","changes":[{"rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3"}],"doc":{"_id":"test2","_rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3","f1":1,"f2":7,"f3":8}}
    ],
    "last_seq":3}
    $ curl
'http://localhost:5984/testdb/_changes?include_docs=true&fields=\["f1"\]'
    {"results":[
    {"seq":1,"id":"test","changes":[{"rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478"}],"doc":{"_id":"test","_rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478","f1":1}},
    {"seq":2,"id":"test1","changes":[{"rev":"1-2942771a428c4b45315710db0b6aaa7a"}],"doc":{"_id":"test1","_rev":"1-2942771a428c4b45315710db0b6aaa7a","f1":1}},
    {"seq":3,"id":"test2","changes":[{"rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3"}],"doc":{"_id":"test2","_rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3","f1":1}}
    ],
    "last_seq":3}

    $ curl
'http://localhost:5984/testdb/_changes?include_docs=true&fields=\["f1","f2"\]'
    {"results":[
    {"seq":1,"id":"test","changes":[{"rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478"}],"doc":{"_id":"test","_rev":"1-2b23983c05a9ca8015b6ea7bdc1b3478","f1":1,"f2":2}},
    {"seq":2,"id":"test1","changes":[{"rev":"1-2942771a428c4b45315710db0b6aaa7a"}],"doc":{"_id":"test1","_rev":"1-2942771a428c4b45315710db0b6aaa7a","f1":1,"f2":4}},
    {"seq":3,"id":"test2","changes":[{"rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3"}],"doc":{"_id":"test2","_rev":"1-ac4cd62a83a0a98421e9ed74adcadcc3","f1":1,"f2":7}}
    ],
    "last_seq":3}

Conflicts:

	apps/couch_changes/src/couch_changes.erl
  • Loading branch information...
commit 227a31cc952d11fb4519424b9ab01af4f982acc8 1 parent d2d3e20
@benoitc benoitc authored
View
16 apps/couch/include/couch_db.hrl
@@ -221,22 +221,6 @@
% small value used in revision trees to indicate the revision isn't stored
-define(REV_MISSING, []).
--record(changes_args, {
- feed = "normal",
- dir = fwd,
- since = 0,
- limit = 1000000000000000,
- style = main_only,
- heartbeat,
- timeout,
- filter = "",
- filter_fun,
- filter_args = [],
- include_docs = false,
- conflicts = false,
- db_open_options = []
-}).
-
-record(btree, {
fd,
root,
View
1  apps/couch_changes/include/couch_changes.hrl
@@ -22,6 +22,7 @@
filter_fun,
filter_args = [],
include_docs = false,
+ fields = [],
conflicts = false,
db_open_options = []
}).
View
31 apps/couch_changes/src/couch_changes.erl
@@ -31,6 +31,7 @@
resp_type,
limit,
include_docs,
+ fields,
conflicts,
timeout,
timeout_fun
@@ -279,6 +280,7 @@ start_sending_changes(Callback, UserAcc, ResponseType) ->
build_acc(Args, Callback, UserAcc, Db, StartSeq, Prepend, Timeout, TimeoutFun) ->
#changes_args{
include_docs = IncludeDocs,
+ fields = Fields,
conflicts = Conflicts,
limit = Limit,
feed = ResponseType,
@@ -294,6 +296,7 @@ build_acc(Args, Callback, UserAcc, Db, StartSeq, Prepend, Timeout, TimeoutFun) -
resp_type = ResponseType,
limit = Limit,
include_docs = IncludeDocs,
+ fields = Fields,
conflicts = Conflicts,
timeout = Timeout,
timeout_fun = TimeoutFun
@@ -505,7 +508,8 @@ changes_row(Results, DocInfo, Acc) ->
#doc_info{
id = Id, high_seq = Seq, revs = [#rev_info{deleted = Del} | _]
} = DocInfo,
- #changes_acc{db = Db, include_docs = IncDoc, conflicts = Conflicts} = Acc,
+ #changes_acc{db = Db, include_docs = IncDoc, fields=Fields,
+ conflicts = Conflicts} = Acc,
{[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Results}] ++
deleted_item(Del) ++ case IncDoc of
true ->
@@ -516,7 +520,16 @@ changes_row(Results, DocInfo, Acc) ->
Doc = couch_index_util:load_doc(Db, DocInfo, Opts),
case Doc of
null -> [{doc, null}];
- _ -> [{doc, couch_doc:to_json_obj(Doc, [])}]
+ _ ->
+ case Fields of
+ [] ->
+
+ [{doc, couch_doc:to_json_obj(Doc, [])}];
+ _ ->
+ JsonObj = couch_doc:to_json_obj(Doc, []),
+ [{doc, filter_doc_fields(Fields,
+ JsonObj, [])}]
+ end
end;
false ->
[]
@@ -585,3 +598,17 @@ filter_docs(Req, Db, DDoc, FName, Docs) ->
[true, Passes] = couch_query_servers:ddoc_prompt(DDoc, [<<"filters">>, FName],
[JsonDocs, JsonReq]),
{ok, Passes}.
+
+filter_doc_fields([], {Props}, Acc) ->
+ Id = proplists:get_value(<<"_id">>, Props),
+ Rev = proplists:get_value(<<"_rev">>, Props),
+ Acc1 = [{<<"_id">>, Id}, {<<"_rev">>, Rev}] ++ lists:reverse(Acc),
+ {Acc1};
+filter_doc_fields([Field|Rest], {Props}=Doc, Acc) ->
+ Acc1 = case couch_util:get_value(Field, Props) of
+ undefined ->
+ Acc;
+ Value ->
+ [{Field, Value} | Acc]
+ end,
+ filter_doc_fields(Rest, Doc, Acc1).
View
2  apps/couch_changes/src/couch_httpd_changes.erl
@@ -131,6 +131,8 @@ parse_changes_query(Req) ->
Args#changes_args{timeout=list_to_integer(Value)};
{"include_docs", "true"} ->
Args#changes_args{include_docs=true};
+ {"fields", _} ->
+ Args#changes_args{fields=?JSON_DECODE(Value)};
{"conflicts", "true"} ->
Args#changes_args{conflicts=true};
{"filter", _} ->
Please sign in to comment.
Something went wrong with that request. Please try again.