我正在使用bulbs和rexster,并尝试存储具有unicode属性的节点(参见下面的示例)。显然,在图中创建节点可以正常工作,因为我可以在rexster (Rexster Dog House)附带的web界面中看到节点,但检索相同的节点却不起作用--我得到的只有None。
当我创建和查找属性中包含非unicode特定字母的节点时,一切都按预期进行。例如,在以下示例中,具有name = u'University of Cambridge'的节点将如预期的那样是可检索的。
Rexster版本:
[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
发布于 2014-04-17 03:35:17
好了,我终于搞清楚了。
由于TinkerGraph使用HashMap作为其索引,因此您可以通过使用Gremlin返回地图的内容来查看索引中存储的内容。
下面是使用上面的灯泡g.university.create(name=name)方法存储在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索引中存储的值。
事情是这样的.
下面是未加引号的字节字符串在灯泡中的样子:
>>> name
u'Universit\xe9 de Montr\xe9al'
>>> bulbs.utils.to_bytes(name)
'Universit\xc3\xa9 de Montr\xc3\xa9al''\xc3\xa9'是unicode字符u'\xe9' (也可以指定为u'\u00e9')的UTF8编码。
UTF-8使用2字节对字符进行编码,Jersey/Grizzly 1.x (Rexster的应用服务器)有一个错误,它不能正确处理像UTF-8这样的2字节字符编码。
请参阅http://markmail.org/message/w6ipdpkpmyghdx2p
看起来这个问题在Jersey/Grizzly 2.0中已经解决了,但是将Rexster从Jersey/Grizzly 1.x切换到Jersey/Grizzly 2.x是一个巨大的考验。
去年TinkerPop决定改用Netty,因此对于今年夏天发布的Gremlin 3,TinkerPop正在向基于Netty而不是Grizzly的Gremlin服务器过渡。
在此之前,这里有几个变通方法...
由于Grizzly不能处理像UTF-8这样的2字节编码,客户端库需要将URL参数编码为1字节latin1编码(AKA 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编码是可行的。
但是,出于一般目的,客户端库最好通过HTTP POST请求对JSON内容类型使用定制的Gremlin脚本,这样就可以完全避免URL param编码问题--这就是Bulbs将要做的事情,我将在今天晚些时候将Bulbs更新推送到GitHub。
更新:事实证明,即使我们不能改变Grizzly的默认编码类型,我们也可以在Content-Type请求头部中指定UTF8作为字符集,Grizzly将使用它。Bulbs 0.3.29已更新,在其请求标头中包含UTF-8字符集,并且所有测试都通过。更新已经被推送到GitHub和PyPi。
https://stackoverflow.com/questions/23057915
复制相似问题