Emit Tuples из Erlang Просмотров в CouchDB - PullRequest
10 голосов
/ 10 марта 2010

CouchDB, версия 0.10.0, с использованием собственных представлений эрланга.

У меня есть простой документ в форме:

{
   "_id": "user-1",
   "_rev": "1-9ccf63b66b62d15d75daa211c5a7fb0d",
   "type": "user",
   "identifiers": [
       "ABC",
       "DEF",
       "123"
   ],
   "username": "monkey",
   "name": "Monkey Man"
}

И базовый проектный документ javascript:

{
   "_id": "_design/user",
   "_rev": "1-94bd8a0dbce5e2efd699d17acea1db0b",
   "language": "javascript",
   "views": {
     "find_by_identifier": {
       "map": "function(doc) {
          if (doc.type == 'user') {
            doc.identifiers.forEach(function(identifier) {
              emit(identifier, {\"username\":doc.username,\"name\":doc.name});
            });
          }
       }"
     }
   }
}

который излучает:

{"total_rows":3,"offset":0,"rows":[
{"id":"user-1","key":"ABC","value":{"username":"monkey","name":"Monkey Man"}},
{"id":"user-1","key":"DEF","value":{"username":"monkey","name":"Monkey Man"}},
{"id":"user-1","key":"123","value":{"username":"monkey","name":"Monkey Man"}}
]}

Я смотрю на создание представления Эрланга, которое делает то же самое. Лучшая попытка на данный момент:

%% Map Function
fun({Doc}) ->
    case proplists:get_value(<<"type">>, Doc) of
    undefined ->
        ok;
    Type ->
        Identifiers = proplists:get_value(<<"identifiers">>, Doc),
        ID = proplists:get_value(<<"_id">>, Doc),
        Username = proplists:get_value(<<"username">>, Doc),
        Name = proplists:get_value(<<"name">>, Doc),
        lists:foreach(fun(Identifier) -> Emit(Identifier, [ID, Username, Name]) end, Identifiers);
    _ ->
        ok
    end
end.

который излучает:

{"total_rows":3,"offset":0,"rows":[
{"id":"user-1","key":"ABC","value":["monkey","Monkey Man"]},
{"id":"user-1","key":"DEF","value":["monkey","Monkey Man"]},
{"id":"user-1","key":"123","value":["monkey","Monkey Man"]}
]}

Вопрос в том, как я могу получить эти значения в виде кортежей, а не массивов? Я не думаю, что могу (или хотел бы) использовать записи, но использование атомов в кортеже, похоже, не работает.

lists:foreach(fun(Identifier) -> Emit(Identifier, {id, ID, username, Username, name, Name}) end, Identifiers);

Сбой со следующей ошибкой:

{"error":"json_encode","reason":"{bad_term,{<<\"user-1\">>,<<\"monkey\">>,<<\"Monkey Man\">>}}"}

Мысли? Я знаю, что Эрланг сосет для такого специфического вида вещей (именованный доступ) и что я могу сделать это по соглашению (идентификатор на первой позиции, имя пользователя затем, настоящее имя фамилия), но это делает код на стороне клиента довольно уродливым.

Ответы [ 3 ]

13 голосов
/ 11 марта 2010

Объект JSON {"foo":"bar","baz":1} равен {[{<<"foo">>,<<"bar">>},{<<"baz">>,1}]}

В Erlang lingua это проплист, завернутый в кортеж.

Это не красиво, но очень эффективно:)

Чтобы почувствовать это, вы можете поиграть с JSON lib, который поставляется с CouchDB:

  1. Запустите CouchDB с -i (интерактивный) флаг
  2. В полученной оболочке erlang введите: couch_util:json_decode(<<"{\"foo\":\"bar\"}">>).
  3. Прибыль

// в более поздних версиях CouchDB, это ejson:decode()

3 голосов
/ 28 ноября 2011

Для test_suite_reports bd с полем tests :

[
   {
       "name": "basics",
       "status": "success",
       "duration": 21795
   },
   {
       "name": "all_docs",
       "status": "success",
       "duration": 385
   } ...

Я написал это, чтобы получить имя и статус:

fun({Doc}) ->
  Name = fun(L) ->  proplists:get_value(<<"name">>, L, null) end,
  Status = fun(L) -> proplists:get_value(<<"status">>, L, null) end,
  Tests = proplists:get_value(<<"tests">>, Doc, null),
  lists:foreach(fun({L}) -> Emit(Name(L), Status(L)) end, Tests)
end.
0 голосов
/ 10 марта 2010

Если вам нравятся экспериментальные функции (которые все еще работают ...), вы можете взглянуть на Erlang exprecs .

Я обнаружил, что это чрезвычайно полезно для создания своего рода динамических записей для Erlang.

...