【问题标题】:Rexster + Bulbs: Unicode node property - node created but not foundRexster + Bulbs:Unicode 节点属性 - 节点已创建但未找到
【发布时间】:2014-05-28 06:49:34
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: unicode bulbs rexster


    【解决方案1】:

    好吧,我终于明白了。

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

    这是使用上述 Bulbs 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')的UTF-8编码。

    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,因此对于今年夏天发布的 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 的默认编码类型,我们也可以在 HTTP 请求 Content-Type 标头中指定 UTF-8 作为字符集,Grizzly 将使用它。 Bulbs 0.3.29 已更新为在其请求标头中包含 UTF-8 字符集,并且所有测试都通过了。该更新已推送到 GitHub 和 PyPi。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-10
      • 2017-07-26
      • 1970-01-01
      • 2016-11-23
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      相关资源
      最近更新 更多