通过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似乎很有用:
答案 0 :(得分:1)
riakc-pb-socket:modify_type
(source 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]).