2016-09-29 8 views
0

更新:Ivan Mainettiの提案に基づいてgithubに問題をオープンしました。あなたがそこに体重を入れたいのであれば、それはです:https://github.com/orientechnologies/orientdb/issues/6757一般Python Unicode/ASCIIキャスティングの問題Pyorientで問題が発生する

私はOrienDBをベースにしたデータベースとそのためのpythonインターフェイスを使っています。私はそれにかなり幸運を覚えましたが、私は特定のユニコード文字を扱うときにドライバー(象徴的な)のような問題に遭遇しました。

私はデータベースにアップロードしていたデータ構造は次のようになります。

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

私はOrientDB/pyorientに完璧レコードの文字通り何百を作成しました。しかし、特定のレコードで失敗する理由は、Ono.absolute_address要素にpyorientが何らかの形で窒息しているユニコード文字があるためです。

私が作成したいレコードが/ U/C/2/A1-2のAbs_addressを持っていますが、私は上記の私のデータ構造体に値を渡すときに私が取得するノードがこれです:

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

私は何とか私の問題は、PythonがユニコードとASCII文字列/文字を混在させていると思いますか?私はPythonに少し新しくタイプを宣言していないので、new_Nodeオブジェクトが適切にフォーマットされた文字列を出力しないとすれば、これはpyorient perseの問題ではないと思っていますか?それとも、これはユニコードを好きではない象徴的な例ですか?私はこの髪を裂いている。どんな助けもありがとうございます。

エラーが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 

それはバックエンドのデータベースがためにnullオブジェクトを取得していることを示唆しているようなエラーが奇数であります住所・アドレス。明らかに、この "アドレス"のエントリを作成しましたが、それは私がしたいものではありません。なぜユニコードのアドレス文字列がデータベース内でヌルになっているのかわかりません...私はnew_Nodeデータ構造体に入力した文字列を使ってorientDBスタジオから作成できますが、私はpythonを使用することはできません同じこと。

誰かが助けますか?

EDIT:ローランへ

おかげで、私はUnicodeオブジェクトおよびpyorientとは何かに問題を絞り込むました。渡している変数がUnicode型である場合、Pyorientアダプタは、OrientDBデータベースにnull値を送ります。私は、問題を引き起こしていることがndashのシンボルの値を決定し、そしてローランは私がこのコード

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

を使用してマイナス記号に置き換える助けた私は、しかし、pyorientは、それがその後、として渡しUnicodeオブジェクトを取得することを行うとnull値...これは良くありません。 str(...)を使用して文字列を再作成することでこの短期的な問題を解決できます。これは私の直面する問題を解決するように見えます:

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

問題は、DBデータにシンボルやその他の異常な文字が含まれることがわかっています。私はデータベースをUnicode文字列をサポートしているので、手動で追加したり、SQL構文を使ってpyorientやpythonで行えないことを行うことができます。これはどこかで問題があると思われていますが、 。これはこの問題と非常によく似ているようです:http://stackoverflow.duapp.com/questions/34757352/how-do-i-create-a-linked-record-in-orientdb-using-pyorient-library

そこの人は誰ですか? Pythonの神ですか?ラッキーなs0bs? =)

+0

データベーススキーマ(存在する場合)を教えてください。 'Nodes.Abs_Address'インデックスはどのように宣言されていますか? –

+0

もちろん、OrientDBスタジオGUIを使用して作成しました。これはString型です。より具体的なものを探しているなら、DBから取得する方法を教えてください。私はあなたのためにそれをつかむことができます。私はOrientDBが初めてです。ありがとう! – user2938099

+1

String型/エンコーディングについても同様の質問があります。http://stackoverflow.com/questions/7381718 –

答えて

1

私はpyorientの開発ブランチで最新のバージョンのOrientDB 2.2.11を使用して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] 

エスケープ値はエスケープ一致しないため、次のテストが失敗しますDBの値がこのようにレコードが返されません。

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' 

この問題を解決するためには、値の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' 

このテストは、DBでエスケープされた値を要求するため、成功します。

+0

アンバー、私が持っているより大きな問題は、私はそれに時折、予測不可能なユニコード文字を持っていない、たくさんのテキストを生成しているということです。私は巨大なxmlファイルからテキストを抜き出し、変数に格納し、上で示したデータ構造に渡してからpyorientで追加しようとしています。私はJSONエンコーディングを使用するあなたの考えが好きです...しかし、私は彼らが前もって何かを知らないので、特定の文字を見つけて置き換えることができません。文字列の内容に関係なく、メソッドが機能すると思いますか? – user2938099

+0

あなたはすでにユニコードのエスケープされた値をDBに保存しているので、おそらくそれをやっておく必要があります。どの値が問題になるか分からないので、すべての値をエスケープする必要があります。クエリを作成するときに、エスケープされていない値を2回エスケープし、表示する必要があるときに元の値にデコードする必要があることを確認する必要があります。私はそれが動作すると確信していますが、確かにあなた自身のユニットテストを書く必要があります。 – anber

関連する問題