From 926af4ba11093dcaff13bea0e4ed9addfc67ab10 Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Wed, 16 Sep 2009 22:04:18 +0000 Subject: include_docs now take an _id (as well as a _rev) in the emitted value, to load docs other than the one doing the emitting. This means you can have one doc list a set of other docs to load in a single query. Enjoy! git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@815984 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/script/test/view_include_docs.js | 26 +++++++++++++++++++++++--- src/couchdb/couch_httpd_db.erl | 2 +- src/couchdb/couch_httpd_view.erl | 13 +++++++------ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/share/www/script/test/view_include_docs.js b/share/www/script/test/view_include_docs.js index 8d50784d..06aafc56 100644 --- a/share/www/script/test/view_include_docs.js +++ b/share/www/script/test/view_include_docs.js @@ -29,6 +29,9 @@ couchTests.view_include_docs = function(debug) { with_prev: { map: "function(doc){if(doc.prev) emit(doc._id,{'_rev':doc.prev}); else emit(doc._id,{'_rev':doc._rev});}" }, + with_id: { + map: "function(doc) {if(doc.link_id) { var value = {'_id':doc.link_id}; if (doc.link_rev) {value._rev = doc.link_rev}; emit(doc._id, value);}};" + }, summate: { map:"function (doc) {emit(doc.integer, doc.integer)};", reduce:"function (keys, values) { return sum(values); };" @@ -84,6 +87,21 @@ couchTests.view_include_docs = function(debug) { T(resp.rows.length == 1); T(resp.rows[0].value == 4950); + T(db.save({ + "_id": "link-to-10", + "link_id" : "10" + }).ok); + + // you can link to another doc from a value. + resp = db.view("test/with_id", {key:"link-to-10"}); + T(resp.rows[0].key == "link-to-10"); + T(resp.rows[0].value["_id"] == "10"); + + resp = db.view("test/with_id", {key:"link-to-10",include_docs: true}); + T(resp.rows[0].key == "link-to-10"); + T(resp.rows[0].value["_id"] == "10"); + T(resp.rows[0].doc._id == "10"); + // Check emitted _rev controls things resp = db.allDocs({include_docs: true}, ["0"]); var before = resp.rows[0].doc; @@ -91,11 +109,13 @@ couchTests.view_include_docs = function(debug) { var after = db.open("0"); after.integer = 100; after.prev = after._rev; - T(db.save(after).ok); + resp = db.save(after) + T(resp.ok); var after = db.open("0"); - T(after._rev != after.prev); - T(after.integer == 100); + TEquals(resp.rev, after._rev, "fails with firebug running"); + T(after._rev != after.prev, "passes"); + TEquals(100, after.integer, "fails with firebug running"); // should emit the previous revision resp = db.view("test/with_prev", {include_docs: true}, ["0"]); diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 03093c41..cdc74610 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -192,7 +192,7 @@ changes_enumerator(DocInfos, {Db, _, Prepend, FilterFun, Resp, _, Limit, Include changes_row(Db, Seq, Id, Del, Results, Rev, true) -> {[{seq,Seq},{id,Id},{changes,Results}] ++ deleted_item(Del) ++ - couch_httpd_view:doc_member(Db, Id, Rev)}; + couch_httpd_view:doc_member(Db, {Id, Rev})}; changes_row(_, Seq, Id, Del, Results, _, false) -> {[{seq,Seq},{id,Id},{changes,Results}] ++ deleted_item(Del)}. diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl index 531e3b6c..489df0a2 100644 --- a/src/couchdb/couch_httpd_view.erl +++ b/src/couchdb/couch_httpd_view.erl @@ -18,7 +18,7 @@ -export([get_stale_type/1, get_reduce_type/1, parse_view_params/3]). -export([make_view_fold_fun/6, finish_view_fold/4, view_row_obj/3]). -export([view_group_etag/2, view_group_etag/3, make_reduce_fold_funs/5]). --export([design_doc_view/5, parse_bool_param/1, doc_member/3]). +-export([design_doc_view/5, parse_bool_param/1, doc_member/2]). -export([make_key_options/1]). -import(couch_httpd, @@ -589,17 +589,18 @@ view_row_obj(Db, {{Key, DocId}, {Props}}, true) -> Rev0 -> couch_doc:parse_rev(Rev0) end, - view_row_with_doc(Db, {{Key, DocId}, {Props}}, Rev); + IncludeId = proplists:get_value(<<"_id">>, Props, DocId), + view_row_with_doc(Db, {{Key, DocId}, {Props}}, {IncludeId, Rev}); view_row_obj(Db, {{Key, DocId}, Value}, true) -> - view_row_with_doc(Db, {{Key, DocId}, Value}, nil); + view_row_with_doc(Db, {{Key, DocId}, Value}, {DocId, nil}); % the normal case for rendering a view row view_row_obj(_Db, {{Key, DocId}, Value}, _IncludeDocs) -> {[{id, DocId}, {key, Key}, {value, Value}]}. -view_row_with_doc(Db, {{Key, DocId}, Value}, Rev) -> - {[{id, DocId}, {key, Key}, {value, Value}] ++ doc_member(Db, DocId, Rev)}. +view_row_with_doc(Db, {{Key, DocId}, Value}, IdRev) -> + {[{id, DocId}, {key, Key}, {value, Value}] ++ doc_member(Db, IdRev)}. -doc_member(Db, DocId, Rev) -> +doc_member(Db, {DocId, Rev}) -> ?LOG_DEBUG("Include Doc: ~p ~p", [DocId, Rev]), case (catch couch_httpd_db:couch_doc_open(Db, DocId, Rev, [])) of #doc{} = Doc -> -- cgit v1.2.3