1

我正在使用bulbs并且rexster正在尝试存储具有 unicode 属性的节点(参见下面的示例)。显然,在图中创建节点可以正常工作,因为我可以在 rexster(Rexster Dog House)附带的 Web 界面中看到节点,但检索相同的节点不起作用 - 我得到的只是None.

当我创建并查找属性中具有非 unicode 特定字母的节点时,一切都按预期工作。例如,在以下示例中,一个节点name = u'University of Cambridge'可以按预期检索。

雷克斯特版本:

[INFO] Application - Rexster version [2.4.0]

示例代码:

# -*- coding: utf-8 -*-


from bulbs.rexster import Graph
from bulbs.model import Node
from bulbs.property import String
from bulbs.config import DEBUG
import bulbs

class University(Node):
    element_type = 'university'
    name = String(nullable=False, indexed=True)


g = Graph()
g.add_proxy('university', University)
g.config.set_logger(DEBUG)

name = u'Université de Montréal'

g.university.create(name=name)

print g.university.index.lookup(name=name)

print bulbs.__version__

在命令行上给出以下输出:

POST url: http://localhost:8182/graphs/emptygraph/tp/gremlin
POST body: {"params": {"keys": null, "index_name": "university", "data": {"element_type": "university", "name": "Universit\u00e9 de Montr\u00e9al"}}, "script": "def createIndexedVertex = {\n vertex = g.addVertex()\n index = g.idx(index_name)\n for (entry in data.entrySet()) {\n if (entry.value == null) continue;\n vertex.setProperty(entry.key,entry.value)\n if (keys == null || keys.contains(entry.key))\n\tindex.put(entry.key,String.valueOf(entry.value),vertex)\n }\n return vertex\n }\n def transaction = { final Closure closure ->\n try {\n results = closure();\n g.commit();\n return results; \n } catch (e) {\n g.rollback();\n throw e;\n }\n }\n return transaction(createIndexedVertex);"} GET url: http://localhost:8182/graphs/emptygraph/indices/university?value=Universit%C3%A9+de+Montr%C3%A9al&key=name
GET body: None None 0.3

4

1 回答 1

2

好的,我终于明白了这一点。

由于 TinkerGraph 使用 HashMap 作为其索引,因此您可以通过使用 Gremlin 返回地图的内容来查看索引中存储的内容。

这是使用g.university.create(name=name)上面的 Bulbs 方法存储在 TinkerGraph 索引中的内容...

$ curl http://localhost:8182/graphs/emptygraph/tp/gremlin?script="g.idx(\"university\").index"
{"results":[{"name":{"Université de Montréal":[{"name":"Université de Montréal","element_type":"university","_id":"0","_type":"vertex"}]},"element_type":{"university":[{"name":"Université de Montréal","element_type":"university","_id":"0","_type":"vertex"}]}}],"success":true,"version":"2.5.0-SNAPSHOT","queryTime":3.732632}

所有这些看起来都不错——编码看起来是正确的。

为了像上面那样创建和索引一个顶点,Bulbs 通过带有 JSON 内容类型的 HTTP POST 请求使用自定义 Gremlin 脚本。

这就是问题所在...

Rexster 的索引查找 REST 端点使用 URL 查询参数,而 Bulbs 将 URL 参数编码为 UTF-8 字节字符串。

为了了解 Rexster 如何处理编码为 UTF-8 字节字符串的 URL 查询参数,我通过一个简单地返回编码字符串的 URL 查询参数执行了一个 Gremlin 脚本......

$ curl http://localhost:8182/graphs/emptygraph/tp/gremlin?script="'Universit%C3%A9%20de%20Montr%C3%A9al'"
{"results":["Université de Montréal"],"success":true,"version":"2.5.0-SNAPSHOT","queryTime":16.59432}

埃加德!那是不对的。如您所见,该文本已损坏。

具有讽刺意味的是,我们让 Gremlin 返回 gremlins,这就是 Rexster 在索引查找中用于键值的内容,正如我们所见,这不是存储在 TinkerGraph 的 HashMap 索引中的内容。

这是发生了什么...

这是 Bulbs 中未加引号的字节字符串的样子:

>>> name
u'Universit\xe9 de Montr\xe9al'

>>> bulbs.utils.to_bytes(name)
'Universit\xc3\xa9 de Montr\xc3\xa9al'

'\xc3\xa9'是 unicode 字符的 UTF-8 编码u'\xe9'(也可以指定为u'\u00e9')。

UTF-8 使用 2 个字节来编码一个字符,而 Jersey/Grizzly 1.x(Rexster 的应用服务器)有一个错误,它不能正确处理 UTF-8 等 2 字节字符编码。

http://markmail.org/message/w6ipdpkpmyghd​​x2p

看起来这在 Jersey/Grizzly 2.0 中已修复,但是将 Rexster 从 Jersey/Grizzly 1.x 切换到 Jersey/Grizzly 2.x 是一个很大的考验。

去年 TinkerPop 决定改用 Netty,因此对于今年夏天发布的 TinkerPop 3,Rexster 正在转变为基于 Netty 而不是 Grizzly 的 Gremlin Server。

在那之前,这里有一些解决方法......

由于 Grizzly 无法处理 UTF-8 等 2 字节编码,因此客户端库需要将 URL 参数编码为 1 字节 latin1 编码(AKA ISO-8859-1),这是 Grizzly 的默认编码。

这是编码为 latin1 字节字符串的相同值...

 $ curl http://localhost:8182/graphs/emptygraph/tp/gremlin?script="'Universit%E9%20de%20Montr%E9al'"
{"results":["Université de Montréal"],"success":true,"version":"2.5.0-SNAPSHOT","queryTime":17.765313}

如您所见,在这种情况下使用 latin1 编码是可行的。

但是,出于一般目的,客户端库最好通过带有 JSON 内容类型的 HTTP POST 请求使用自定义 Gremlin 脚本,从而避免 URL 参数编码问题——这就是 Bulbs 要做的事情,并且我将在今天晚些时候将 Bulbs 更新推送到 GitHub。

更新:事实证明,即使我们无法更改 Grizzly 的默认编码类型,我们也可以将 UTF-8 指定为 HTTP 请求Content-Type标头中的字符集,并且 Grizzly 将使用它。Bulbs 0.3.29 已更新为在其请求标头中包含 UTF-8 字符集,并且所有测试都通过了。该更新已推送到 GitHub 和 PyPi。

于 2014-04-16T19:35:17.427 回答