Erlang - 从Couch DB视图中有条件地省略一个属性

时间:2014-12-11 16:50:08

标签: syntax mapreduce erlang couchdb conditional

我有一个呈现JSON对象的Erlang Couch DB,如下所示:

fun({Doc}) ->
    Name = couch_util:get_value(<<\"name\">>, Doc),
    Value = couch_util:get_value(<<\"Value\">>, Doc),
    Geocode = couch_util:get_value(<<\"geocode\">>, Doc),
    Emit(
        Name,
        {[
            { <<\"value\">>,Value }, 
            { <<\"geocode\">>, Geocode }            
        ]}
    )
end.

问题是此视图中的所有文档都没有“地理编码”属性。在没有地理编码的情况下,我宁愿不显示它。在伪代码中,我基本上想要这个......

Emit(
    Name,
    {[
        { <<\"value\">>,Value }, 
        Geocode != undefined ? { <<\"geocode\">>, Geocode } : null  
    ]}
);

我怀疑在Erlang中执行此操作并不容易?

到目前为止,我最好的解决方案是:

fun({Doc}) ->
    Name = couch_util:get_value(<<\"name\">>, Doc),
    Value = couch_util:get_value(<<\"Value\">>, Doc),
    Geocode = couch_util:get_value(<<\"geocode\">>, Doc),
    % I think 'couch_util:get_value' returns the atom undefined, if the value doesn't exist.
    Undefined = undefined,
    if Geocode /= Undefined ->
        Emit(
            Name,
            {[
                { <<\"value\">>, Value }, 
                { <<\"geocode\">>, Geocode }            
            ]}
        );
    true -> Emit(Name, {[ { <<\"value\">>, Value } ]})
    end;
end.

非常确定那里会有一两个语法错误...请随意指出它们! 但更重要的是,是否有更有效的方法从条件清单/视图中有条件地删除“地理编码”值?

1 个答案:

答案 0 :(得分:2)

您要做的是过滤掉缺失的属性。

让我们用list comprehension

创建一个proplist

ListOfKeys = [<<"value">>, <<"geocode">>], Proplist = [{Key, couch_util:get_value(Key, Doc)} || Key <- ListOfKeys],

并让我filter/2出具undefined值的道具:

FilteredProplist = lists:filter( fun ({_Key, undefined}) -> false; % it matches => it's out ({_Key, _Value}) -> true end, Proplist),

现在你可以Emit(Name, FilteredProplist)

也可以在列表理解中过滤掉它们,但看起来并不清楚:

FilteredProplist = [{Key, Value} || Key <- ListOfKeys, Value <- [couch_util:get_value(Key, Doc)], Value /= undefined]

编辑: 哦......我想我错过了最重要的问题:如何在erlang中编写它?

{[ { <<\"value\">>,Value }, Geocode != undefined ? { <<\"geocode\">>, Geocode } : null ]}

答案是:

{ [{ <<"value">>,Value }] ++ if Geocode /= undefined -> [{ <<"geocode">>, Geocode }]; true -> [] end }