web-dev-qa-db-ja.com

Cassandra CQLで「入力 'なし'で実行可能な代替がありません」エラーが発生する原因

変更されたドキュメントをCassandra DBに新しいキーで挿入しようとしています。エラーメッセージが指している問題の原因を特定するのに苦労しています。他のユーザーを探すとき同様の問題があった回答はキーに関連しているようで、私の場合、Noneはいくつかのキーの値にすぎません。この問題を解決するにはどうすればよいですか?

keys = ','.join(current.keys())
params = [':' + x for x in current.keys()]
values = ','.join(params)

query = "INSERT INTO wiki.pages (%s) Values (%s)" % (keys, values)
query = query.encode('utf-8')
cursor.execute(query, current)

クエリと現在のデータは次のとおりです。

INSERT INTO wiki.pages (changed,content,meta,attachment,revision,page,editor) 
VALUES (:changed,:content,:meta,:attachment,:revision,:page,:editor)

{
    u'changed': '2013-02-15 16:31:49', 
    u'content': 'Testing', 
    u'meta': None, 
    u'attachment': None,    
    u'revision': 2, 
    u'page': u'FrontPage', 
    u'editor': 'Anonymous'
}

これは次のエラーで失敗します。

cql.apivalues.ProgrammingError: 
Bad Request: line 1:123 no viable alternative at input 'None'
11
Fuu

「実行可能な代替がない」とは、一部のキーのデータ型がその列ファミリーの列のスキーマと一致しないことを意味しますが、残念ながらエラーメッセージにはその旨が明記されていません。

私の場合、メタのデータ型は次のとおりです。

map<text,text> 

このため、Noneは挿入時に悪い値と見なされていました。挿入する前にNoneを空のdictに置き換えることで問題を修正しました:

if current['meta'] is None:
    current['meta'] = dict()

CQLドライバーはマップタイプの新しい値として空のdictを受け入れますが、マップ列をクエリすると空の場合はNoneが返されますが、Noneは許可されません。

Noneを返し、Noneを受け入れないことは直感的に感じられなかったため、後で、列のリストではなく列のマップを返し、MapType、ListType、またはSetTypeがNoneを返したかどうかを確認する、cursor.fetchone()のカスタムラッパーを作成することにしました。 。 None値がある場合は、空のdict()、list()、またはset()に置き換えて、変更されたデータをCassandraに挿入するときに発生したような問題を回避します。これはうまく動作するようです。

13
Fuu