今早查看,是的……HTTP API 和 URL 编码的索引名称和索引值存在问题。
问题是这样的:标题名称和值不是 URL 解码并在您发布时按原样存储,但是当您发出 GET 请求时,URL 的分层部分(其中包含索引名称和值)被解码。此外,+ 而不是 %20 也是一个问题。
如果您使用 %20 并通过 URL 转义 GET,它实际上可以工作(注意我将 £ 替换为 %A3):
curl -X POST -H 'x-riak-index-Indexed%20field%20name%20%40%24%40%24%40%20%40%24%20not%20url%20safe%23%40%C2%A3%21_bin: index%20%40%24%20value' -d 'Some Value' http://localhost:8098/buckets/test_bucket/keys/my_key
然后
curl localhost:8098/buckets/test_bucket/index/Indexed%2520field%2520name%2520%2540%2524%2540%2524%2540%2520%2540%2524%2520not%2520url%2520safe%2523%2540%25C2%25A3%2521_bin/index%2520%2540%2524%2520value
结果:
{"keys":["my_key"]}
另一方面,协议缓冲区不会遇到这些问题。如果您将 Java 客户端与协议缓冲区一起使用,则以下操作可以正常工作(注意客户端会不自动对索引参数进行 url 编码,就像它对键和存储桶一样):
IRiakClient client = RiakFactory.pbcClient();
Bucket b = client.fetchBucket("test_bucket").execute();
String s = "Indexed field name @$@$@ @$ not url safe#@£!";
String s2 = URLEncoder.encode(s, "UTF-8");
System.out.println(s2);
String v = "index @$ value";
String v2 = URLEncoder.encode(v, "UTF-8");
System.out.println(v2);
IRiakObject ro = RiakObjectBuilder.newBuilder("test_bucket", "key")
.addIndex(s2, v2)
.withValue("Some value")
.build();
b.store(ro).execute();
List<String> index = b.fetchIndex(BinIndex.named(s2))
.withValue(v2)
.execute();
System.out.println(index);
client.shutdown();
输出:
索引+字段+名称+%40%24%40%24%40+%40%24+not+url+safe%23%40%C2%A3%21
指数+%40%24+价值
[关键]
实际上,协议缓冲区根本不需要您进行 URL 编码……它会通过 UTF8 字节发送并愉快地将它们用作索引名称和值。您可以从上面的示例中删除 URL 编码并查看它是否有效。
不幸的是,如果您尝试在其他地方使用 HTTP,这肯定会出现问题。因为 java 中包含的 URLEncoder 类使用 +,所以使用使用 %20 的不同 URL 编码器(或执行 String.replaceAll())会有所帮助,但您仍然必须处理使用 HTTP 的 URL 转义查询。
归结为,如果您使用 HTTP API,带有 2i 的非 US-ASCII(或特殊字符)会出现问题。
更新:我认为这很容易解决,并有一个 PR:https://github.com/basho/riak_kv/pull/543 - 最后讨论了一个问题,因此可能需要额外的工作。我们目前将冻结 riak 1.4 的代码,因此可能要到下一个版本才能使用。