1

我正在使用 Riak 1.3.1 并试图创建一个二进制索引名称Indexed field name @$@$@ @$ not url safe#@£!。我能够使用此索引成功保存密钥。

当我直接使用键值查询此键时,我得到以下结果:

{"indexedFieldValue":"index @$ value","keyValue":"093741d5-940a-49a6-b742-be22c1773e87","indexes":{"Indexed field name @$@$@ @$ not url safe#@£!":"index @$ value"}}

现在,当我尝试使用 URL 使用此索引进行查询时/index/Indexed+field+name+%40%24%40%24%40+%40%24+not+url+safe%23%40£%21_bin/value,我绝对没有收到任何响应: {"keys":[]}

  • 我做错了什么,还是
  • Riak 不支持需要 URL 编码的索引名称吗?

注意:我使用 Riak Java 客户端写入数据(并在使用 Java 客户端通过二级索引查询时得到相同的结果),但我看不出 Java 客户端应该与此有什么关系。

谢谢!!

4

1 回答 1

2

今天早上看这个,是的...... HTTP API 和 URL 编码的索引名称和索引值存在问题。

问题是这样的:标头名称和值不是URL 解码的,并且在您 POST 时按原样存储,但是当您发出 GET 请求时,URL 的分层部分(包含索引名称和值)解码。此外,+不是%20任何一个都是一个问题。

如果您使用%20GET 并对其进行 URL 转义,它实际上可以工作(注意我替换£%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();

输出:

indexed+field+name+%40%24%40%24%40+%40%24+not+url+safe%23%40%C2%A3%21
index+%40%24+value
[key]

事实上,协议缓冲区根本不需要您进行 URL 编码……它会通过 UTF8 字节发送并愉快地将它们用作索引名称和值。您可以从上面的示例中删除 URL 编码并查看它是否有效。

不幸的是,如果您尝试在其他地方使用 HTTP,这肯定会出现问题。因为URLEncoderjava 中包含的类 uses +,所以使用不同的 URL 编码器使用%20(或做 a String.replaceAll())会有所帮助,但您仍然必须处理 HTTP 查询的 URL 转义。

归根结底,如果您使用 HTTP API,2i 的非 US-ASCII(或特殊字符)会出现问题。

更新:我认为这很容易解决并有一个 PR:https ://github.com/basho/riak_kv/pull/543 - 最后讨论了一个问题,因此可能需要额外的工作。我们目前将冻结 riak 1.4 的代码,因此可能要到下一个版本才能使用。

于 2013-05-02T15:26:53.330 回答