【问题标题】:Emit Tuples From Erlang Views In CouchDB在 CouchDB 中从 Erlang 视图中发出元组
【发布时间】:2011-01-25 18:25:44
【问题描述】:

CouchDB,版本 0.10.0,使用原生 erlang 视图。

我有一个简单的文件格式:

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

我正在研究建立一个做同样事情的 Erlang 视图。迄今为止最好的尝试是:

%% 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\">>}}"}

想法?我知道 Erlang 不适合这种特定类型的事情(命名访问),而且我可以按照约定(id 在第一位,用户名在后,真名在后)来做到这一点,但这使得客户端代码非常难看。

【问题讨论】:

  • 我不知道 CouchDB 的详细信息,所以我不知道 Emit 指的是什么函数,但显然 CouchDB 中使用的 json_encode 需要一个列表作为输入。见:svn.apache.org/viewvc/couchdb/trunk/src/couchdb/…
  • Emit 是从 map 函数返回数据的函数,以便稍后减少。它在 JS 版本中有一个等价物,我认为它们都内置在 CouchDB 视图机制中。感谢您的链接。这就解释了为什么它不起作用。现在,要了解如何解决它:)
  • 我知道一般的emit是什么;我只是不知道您粘贴的代码中Emit 变量引用的函数。
  • 能否请您指出如何使用职位来做到这一点?

标签: erlang couchdb tuples


【解决方案1】:

如果您喜欢实验性功能(仍然可以使用...),您可能想看看 Erlang exprecs

我发现它对于为 Erlang 创建一种动态记录非常有帮助。

【讨论】:

    【解决方案2】:

    JSON 对象 {"foo":"bar","baz":1}{[{&lt;&lt;"foo"&gt;&gt;,&lt;&lt;"bar"&gt;&gt;},{&lt;&lt;"baz"&gt;&gt;,1}]}

    在 Erlang lingua 中,它是一个包裹在元组中的 proplist。

    它不漂亮,但非常有效:)

    要感受一下,您可以使用 CouchDB 附带的 JSON 库:

    1. 使用 -i 启动 CouchDB (交互式)标志
    2. 在生成的 erlang shell 上,键入:couch_util:json_decode(&lt;&lt;"{\"foo\":\"bar\"}"&gt;&gt;).
    3. 利润

    // 在 CouchDB 的更高版本中,这是ejson:decode()

    【讨论】:

    • 完美!这真的很有帮助:)
    • 解码具有嵌套键的json时,是否也需要用\{转义{?
    【解决方案3】:

    对于 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.
    

    【讨论】:

      猜你喜欢
      • 2014-05-24
      • 2018-11-04
      • 2011-10-11
      • 2012-03-02
      • 2014-04-18
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多