使用Erlang客户端通过协议缓冲区从Riak集中删除元素而不获取整个集合

时间:2015-01-27 11:20:09

标签: erlang protocol-buffers riak

通过HTTP API,我们可以从集合中删除任意元素,而无需获取整个内容:

curl -X POST http://127.0.0.1:8098/types/sets/buckets/travel/datatypes/cities -H "content-type: application/json" -d '{ "remove" : "Toronto" }'

(验证:     tcpdump -i any -s 0 -n 'src port 8087 or src port 8098 and host 127.0.0.1'

但是通过协议缓冲客户端,我们需要执行以下步骤才能从集合中删除元素:

{ok, MySet} = case riakc_pb_socket:fetch_type(Pid, {<<"sets">>, <<"travel">>}, <<"cities">>) of {error,{notfound,set}}-> {ok, riakc_set:new()}; {ok, Set} -> {ok, Set}  end.
ModSet=riakc_set:del_element(lists:last(ordsets:to_list(riakc_set:value(MySet))), MySet).
riakc_pb_socket:update_type(Pid, {<<"sets">>, <<"travel">>}, <<"cities">>, riakc_set:to_op(ModSet)).

顾名思义,riakc_pb_socket:fetch_type检索整个集合。我在Erlang客户端中找不到任何使用protobuf的方法来发送删除请求而不先检索整个集合。

有没有办法在删除元素时避免通过protobuf客户端获取整个集合对象?

更新:协议缓冲区更新数据类型的API似乎很有用:

1 个答案:

答案 0 :(得分:1)

riakc-pb-socket:modify_typesource code)的最后一个参数是一组更改。如果你已经知道要删除哪个元素,理论上你可以创建一个新的空集并构建一个删除操作

Empty = riakc_set:new(Context),
Removal = riakc_set:del_element(<<"Toronto">>,Empty),
Op = riakc_set:to_op(Removal),
riakc_pb_socket:update_type(Pid, {<<"sets">>, <<"travel">>}, <<"cities">>, Op).

这里的关键是Context,它是服务器生成的不透明值。您可以在没有一个请求的情况下发送请求,也可以使用空的请求(<<>>)发送请求,但这可能不是Good Thing(tm)。上下文是Riak如何确定因果关系。每次采取行动时,每个行动者都会更新它,并用于确定最终的一致值。因此,如果您发送没有上下文的集合操作,它可能会失败或被无序处理,特别是如果在同一时间发生任何其他更新。

对于HTTP API,协调器获取整个对象以获取上下文,然后使用该上下文提交操作。

执行常规get操作时,您可以在选项中指定head以仅返回元数据,其中包括上下文,但不包括数据。我还没有使用fetch_type进行测试,但是对于融合类型可能有类似的功能。如果有,您只需要获取头部以获取上下文,并使用该上下文提交操作。

CNC中
根据{{​​3}}:

  

%%您无法使用Erlang直接获取数据类型的上下文   %%客户。这实际上是完全正确的,因为客户端自动
  %%在进行更新时管理上下文。

看起来您可以将乐趣传递给riakc_pb_socket:modify_type,这样您就不必显式获取旧值,但这只会在幕后获取它,所以您只需要保存一点点代码。

riakc_pb_socket:modify_type(Pid,
            fun(MySet) -> riakc_set:del_element(lists:last(ordsets:to_list(riakc_set:value(MySet))), MySet)
            end, {<<"sets">>, <<"travel">>}, <<"cities">>,[create]).