使用 Erlang 客户端通过协议缓冲区从 Riak 集中删除元素而不获取整个集合
Deleting an element from a Riak set via protocol buffers using the Erlang client without fetching the whole set
通过 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'
)
然而,通过 protocol buffers 客户端,我们需要执行以下步骤才能从集合中删除元素:
{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 更新数据类型似乎很有用:
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 测试过,但收敛类型可能有类似的功能。如果有,您只需要获取头部以获取上下文,然后使用该上下文提交您的操作。
-编辑-
根据 docs:
%% You cannot fetch a Data Type's context directly using the Erlang
%% client. This is actually quite all right, as the client automatically
%% manages contexts when making updates.
您似乎可以将一个 fun 传递给 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]).
通过 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'
)
然而,通过 protocol buffers 客户端,我们需要执行以下步骤才能从集合中删除元素:
{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 更新数据类型似乎很有用:
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 测试过,但收敛类型可能有类似的功能。如果有,您只需要获取头部以获取上下文,然后使用该上下文提交您的操作。
-编辑-
根据 docs:
%% You cannot fetch a Data Type's context directly using the Erlang
%% client. This is actually quite all right, as the client automatically
%% manages contexts when making updates.
您似乎可以将一个 fun 传递给 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]).