erlang_couchdbのコードをチラ見(2009/11/11, 11/12追記)
ミニマリズムな実装ということで、ngerakines/erlang_couchdb · GitHubをgit cloneしてみた。
とりあえず自分の手(目)の届くサイズなのはありがたい。Makefileとか、これくらいなら読めるw。
要するに、erlang_couchdb.erlが本体で、couchdb.erlはAPIをシンプルにした(というかヘッダファイルに定義したもので決めウチした)wrapperである。
CouchDBのアクセスで面白みがあるのはViewとかのアクセスで、JSON形式でqueryを投げる部分で、その基本形は次のようになっている。(註:build_uriの部分とか、関数を展開している)
ViewClassってナンだろ?とか、Viewはどっから来るのか?とか一瞬戸惑うが、後者はlistの内包表記(list comprehension)であることに気づけばなんとかわかる。
mochijson2で処理しているのである程度unicodeも処理できそうである。
create_view({Server, ServerPort}, Database, ViewClass, Language, Views, Attributes) when is_list(Server), is_integer(ServerPort) -> Design = [ {<<"_id">>, list_to_binary("_design/" ++ ViewClass)}, {<<"language">>, Language}, {<<"views">>, {struct, [ begin case View of {Name, Map} -> {Name, {struct, [{<<"map">>, Map}]}}; {Name, Map, Reduce} -> {Name, {struct, [{<<"map">>, Map}, {<<"reduce">>, Reduce }]}} end end || View <- Views ]}} | Attributes], JSON = list_to_binary(mochijson2:encode({struct, Design})), Url =lists:concat(["/", Database, "/", "_design/" ++ ViewClass]), raw_request("PUT", Server, ServerPort, Url, JSON).
テスト、というか、自作couchdbアクセスのコードと置換したら追記予定。
Viewによるアクセスのテストをしてみた(2009/11/11追記、11/12変更あり)
common testのテストケースにしてみた。参照:erlang_couchdb/test/erlang_couchdb_SUITE.erl at master · kgbu/erlang_couchdb · GitHub(2009/11/12リンクを変更)
ただし、erlang_couchdbのライブラリの引数が一部binaryになっているところがあったので、それらはlistをとってくれるように変更した。githubでforkしたので、変更内容はこのcommitを参照のこと。これも決定版では全然無いのであしからず。
viewaccess_nullmap(_Config) -> do_viewaccess_maponly("function(doc) { emit(null, doc)}") . viewaccess_maponly(_Config) -> do_viewaccess_maponly("function(doc) { if(doc.type) {emit(null, doc.type)}}") . do_viewaccess_maponly(Viewsource) -> % setup ok = erlang_couchdb:create_database(?CONNECTION, ?DBNAME), {json,{struct,[_, {<<"id">>, Id},_]}} = erlang_couchdb:create_document(?CONNECTION, ?DBNAME, {struct, [{<<"type">>, <<"D">> } ]}), {json,{struct,[_, {<<"id">>, Id2},_]}} = erlang_couchdb:create_document(?CONNECTION, ?DBNAME, {struct, [{<<"type">>, <<"S">> } ]}), Doc = erlang_couchdb:retrieve_document(?CONNECTION, ?DBNAME, binary_to_list((Id))), ct:print(test_category, "Document: ~p", [Doc]), Doc2 = erlang_couchdb:retrieve_document(?CONNECTION, ?DBNAME, binary_to_list(Id2)), ct:print(test_category, "Document2: ~p", [Doc2]), Views = [{"all", Viewsource}], Res = erlang_couchdb:create_view(?CONNECTION, ?DBNAME, "testview", "javascript", Views, []), ct:print("view creation result: ~p~n",[Res]), % view access ResView = erlang_couchdb:invoke_view(?CONNECTION, ?DBNAME, "testview", "all",[]), ct:print("view access result: ~p~n",[ResView]), % tear down ok = erlang_couchdb:delete_database(?CONNECTION, ?DBNAME) .
実行すると、こんな感じ
---------------------------------------------------- 03:07:43 test_category Document: {json,{struct,[{<<"_id">>,<<"95bc6c2757334cfbc79bd1f099d8dee4">>}, {<<"_rev">>,<<"1-d956df5512967b46ec517e002f492bb5">>}, {<<"type">>,<<"D">>}]}} ---------------------------------------------------- 03:07:43 test_category Document2: {json,{struct,[{<<"_id">>,<<"8e77afa90e104fd8d9b1b53868bc40f5">>}, {<<"_rev">>, <<"1-b97600d0f9e1b2dcb077c80cab8a8eb2">>}, {<<"type">>,<<"S">>}]}} ---------------------------------------------------- 03:07:43 view creation result: {json,{struct,[{<<"ok">>,true}, {<<"id">>,<<"_design/testview">>}, {<<"rev">>, <<"1-5e2042ca2ce1310bd1697a834cb6e97a">>}]}} ---------------------------------------------------- 03:07:43 view access result: {json, {struct, [{<<"total_rows">>,2}, {<<"offset">>,0}, {<<"rows">>, [{struct, [{<<"id">>,<<"8e77afa90e104fd8d9b1b53868bc40f5">>}, {<<"key">>,null}, {<<"value">>, {struct, [{<<"_id">>, <<"8e77afa90e104fd8d9b1b53868bc40f5">>}, {<<"_rev">>, <<"1-b97600d0f9e1b2dcb077c80cab8a8eb2">>}, {<<"type">>,<<"S">>}]}}]}, {struct, [{<<"id">>,<<"95bc6c2757334cfbc79bd1f099d8dee4">>}, {<<"key">>,null}, {<<"value">>, {struct, [{<<"_id">>, <<"95bc6c2757334cfbc79bd1f099d8dee4">>}, {<<"_rev">>, <<"1-d956df5512967b46ec517e002f492bb5">>}, {<<"type">>,<<"D">>}]}}]}]}]}} ---------------------------------------------------- 03:07:43 test_category Document: {json,{struct,[{<<"_id">>,<<"676304eaac4cf1bae12211477f0ec25c">>}, {<<"_rev">>,<<"1-d956df5512967b46ec517e002f492bb5">>}, {<<"type">>,<<"D">>}]}} ---------------------------------------------------- 03:07:43 test_category Document2: {json,{struct,[{<<"_id">>,<<"cf53e11fce3d233c01b52da10932ab00">>}, {<<"_rev">>, <<"1-b97600d0f9e1b2dcb077c80cab8a8eb2">>}, {<<"type">>,<<"S">>}]}} ---------------------------------------------------- 03:07:43 view creation result: {json,{struct,[{<<"ok">>,true}, {<<"id">>,<<"_design/testview">>}, {<<"rev">>, <<"1-321472ffe98d89d02a97770678533a1c">>}]}} ---------------------------------------------------- 03:07:43 view access result: {json, {struct, [{<<"total_rows">>,2}, {<<"offset">>,0}, {<<"rows">>, [{struct, [{<<"id">>, <<"676304eaac4cf1bae12211477f0ec25c">>}, {<<"key">>,null}, {<<"value">>,<<"D">>}]}, {struct, [{<<"id">>, <<"cf53e11fce3d233c01b52da10932ab00">>}, {<<"key">>,null}, {<<"value">>,<<"S">>}]}]}]}}