0

更新:我根据 Ivan Mainetti 的建议在 github 上打开了一个问题。如果你想在那里称重,它是:https ://github.com/orientechnologies/orientdb/issues/6757

我正在开发一个基于 OrienDB 的数据库并为其使用 python 接口。我已经很幸运了,但是在处理某些 unicode 字符时,我遇到了一个似乎是驱动程序(pyorient)的问题。

我上传到数据库的数据结构如下所示:

new_Node = {'@Nodes':
                {
                    "Abs_Address":Ono.absolute_address,
                    'Content':Ono.content,
                    'Heading':Ono.heading,
                    'Type':Ono.type,
                    'Value':Ono.value
                }
}

我已经在 OrientDB / pyorient 上完美地创建了数百条记录。但是,我认为问题不一定是特定于 pyorient 的问题,因为我认为它在特定记录上失败的原因是因为 Ono.absolute_address 元素具有 pyorient 不知何故窒息的 unicode 字符。

我要创建的记录的 Abs_address 为 /u/c/2/a1–2,但是当我将值传递给上面的数据结构时得到的节点是这样的:

{'@Nodes': {'Content': '', 'Abs_Address': u'/u/c/2/a1\u20132', 'Type': 'section', 'Heading': ' Transferred', 'Value': u'1\u20132'}}

我认为我的问题是python混合了unicode和ascii字符串/字符?我对python有点陌生并且没有声明类型,所以我希望这不是pyorient perse的问题,因为new_Node对象没有输出格式正确的字符串......?或者这是 pyorient 不喜欢 unicode 的一个实例?我正在把头发扯下来。任何帮助表示赞赏。

如果错误来自 pyorient 而不是某种文本编码,这里是 pyorient 相关信息。我正在使用以下代码创建记录:

rec_position = self.pyo_client.record_create(14, new_Node)

这是我得到的错误:

com.orientechnologies.orient.core.storage.ORecordDuplicatedException - Cannot index record Nodes{Content:,Abs_Address:null,Type:section,Heading: Transferred,Value:null}: found duplicated key 'null' in index 'Nodes.Abs_Address' previously assigned to the record #14:558

该错误很奇怪,因为它表明后端数据库正在获取地址的空对象。显然它确实为这个“地址”创建了一个条目,但这不是我想要的。我不知道为什么带有 unicode 的地址字符串在数据库中为空...我可以通过 orientDB studio 使用我输入 new_Node 数据结构的确切字符串创建它...但我不能使用 python 来做同样的事情。

有人帮忙吗?

编辑:

感谢 Laurent,我将问题缩小到与 unicode 对象和 pyorient 有关的问题。每当我传递的变量是 unicode 类型时,pyorient 适配器就会向 OrientDB 数据库发送一个空值。我确定导致问题的值是一个 ndash 符号,Laurent 使用此代码帮助我用减号替换它

.replace(u"\u2013",u"-")

但是,当我这样做时,pyorient 会获取 unicode 对象,然后将其作为空值传递……这不好。我可以通过使用 str(...) 重铸字符串来解决这个短期问题,这似乎解决了我的直接问题:

str(Ono.absolute_address.replace(u"\u2013",u"-"))

. 问题是,我知道我的数据库数据中会有符号和其他不寻常的字符。我知道数据库支持 unicode 字符串,因为我可以手动添加它们或使用 SQL 语法来做我不能通过 pyorient 和 python 做的事情......我假设这是一个冒险的转换问题,但我不确定在哪里. 这似乎与这个问题非常相似:http ://stackoverflow.duapp.com/questions/34757352/how-do-i-create-a-linked-record-in-orientdb-using-pyorient-library

那里有pyorient人吗?蟒蛇之神?幸运的s0bs?=)

4

1 回答 1

1

我已经使用最新版本的 OrientDB 2.2.11 的 pyorient 开发分支在 Python 3 上尝试了您的示例。如果我传递值而不转义它们,那么您的示例似乎对我有用,并且我得到了正确的值。

所以这个测试有效:

def test_test1(self):
    new_Node = {'@Nodes': {'Content': '',
                           'Abs_Address': '/u/c/2/a1–2',
                           'Type': 'section',
                           'Heading': ' Transferred',
                           'Value': u'1\u20132'}
                }

    self.client.record_create(14, new_Node)

    result = self.client.query('SELECT * FROM V where Abs_Address="/u/c/2/a1–2"')
    assert result[0].Abs_Address == '/u/c/2/a1–2'

我认为您可能会将 unicode 值保存为转义值,这就是事情变得棘手的地方。

我不相信自己替换值,所以我通常使用以下代码转义发送到 orientdb 的 unicode 值:

import json
def _escape(string):
    return json.dumps(string)[1:-1]

以下测试将失败,因为转义值与数据库中的转义值不匹配,因此不会返回任何记录:

def test_test2(self):
    new_Node = {'@Nodes': {'Content': '',
                           'Abs_Address': _escape('/u/c/2/a1–2'),
                           'Type': 'section',
                           'Heading': ' Transferred',
                           'Value': u'1\u20132'}
                }

    self.client.record_create(14, new_Node)

    result = self.client.query('SELECT * FROM V where Abs_Address="%s"' % _escape('/u/c/2/a1–2'))
    assert  result[0].Abs_Address.encode('UTF-8').decode('unicode_escape') == '/u/c/2/a1–2'

为了解决这个问题,您必须两次转义该值:

def test_test3(self):
    new_Node = {'@Nodes': {'Content': '',
                           'Abs_Address': _escape('/u/c/2/a1–2'),
                           'Type': 'section',
                           'Heading': ' Transferred',
                           'Value': u'1\u20132'}
                }

    self.client.record_create(14, new_Node)

    result = self.client.query('SELECT * FROM V where Abs_Address="%s"' % _escape(_escape('/u/c/2/a1–2')))
    assert  result[0].Abs_Address.encode('UTF-8').decode('unicode_escape') == '/u/c/2/a1–2'

此测试将成功,因为您现在将要求数据库中的转义值。

于 2016-10-12T04:37:03.533 回答