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">>}]}]}]}}