使用 python 驱动程序在 Cassandra 中插入元组字段

hem*_*lus 4 python tuples cassandra

大家,

我在通过 DataStax 提供的将数据插入 Cassandra 表上的元组值字段时遇到问题python-driver

要么我不知道如何正确地将元组参数传递给命令Session.execute,要么驱动程序在将元组分派到 Cassandra 时以错误的方式在内部转换元组 - 因为在会话中执行时相同的插入工作正常cqlsh

不涉及元组而是列表的等效插入在代码和cqlsh.

我正在使用 Python 2.7.10 和 cassandra-driver 3.7.1。Python 执行中引发的错误是InvalidRequest: Error from server: code=2200 [Invalid query] message="Invalid list literal for tuplefield of type frozen<tuple<int, int, int>>"

我在下面粘贴了一个最小的工作代码,它重现了我所看到的问题。有人可以帮我弄清楚我是否做错了什么吗?

(注意:我已经尝试过传递一个普通的 List 来Session.execute代替 tuple 参数,但也没有成功。)

非常感谢。

'''
    Run with:
        python 2.7.10
        cassandra-driver==3.7.1 installed
'''

from cassandra.cluster import Cluster

if __name__=='__main__':

    serverAddress='SERVER_ADDRESS'
    keyspacename='tupletests'
    tablecreation='''create table tabletest (
                            rowid int,
                            tuplefield tuple < int, int, int >,
                            listfield list < int >,
                        primary key (rowid)
                    );'''

    # connect and create keyspace
    clu=Cluster([serverAddress])
    session=clu.connect()
    session.execute("create keyspace %s with replication = \
        {'class': 'SimpleStrategy', 'replication_factor': 1};" % keyspacename)

    # use keyspace; create a sample table
    session.set_keyspace(keyspacename)
    session.execute(tablecreation)

    # insert a row with rowid,listfield
    session.execute('insert into tabletest (rowid, listfield) values (%s,%s)', \
        [999, [10,11,12]])
    # succeeds

    # insert a row with rowid,tuplefield
    session.execute('insert into tabletest (rowid, tuplefield) values (%s,%s)', \
        [111, tuple([6,5,4])])
    # raises: *** InvalidRequest: Error from server: code=2200 [Invalid query]
    # message="Invalid list literal for tuplefield of type frozen<tuple<int, int, int>>"

    # Compare with analogous statements in cqlsh, which *both* succeed:
    # List:    insert into tabletest (rowid, listfield) values (999, [21,22,23]);
    # Tuple:   insert into tabletest (rowid, tuplefield) values (765, (121,122,123));

    # delete test keyspace
    session.execute("drop keyspace %s;" % keyspacename)    
    print "Test Finished."
Run Code Online (Sandbox Code Playgroud)

hem*_*lus 5

好的,我刚刚解决了这个问题。在这里为大家发布解决方案。为了让驱动程序知道元组在传递给 Cassandra 时应如何格式化,如果坚持使用非准备语句进行插入,则必须在调用插入之前指定解析元组时要使用的编码器:

session.encoder.mapping[tuple] = session.encoder.cql_encode_tuple
Run Code Online (Sandbox Code Playgroud)

在此语句之后,出现在Session.executeinsert 语句中的元组会自动以 Cassandra 的正确方式进行转换,而 Cassandra 不再抱怨。

(据我了解,最好采用Prepared语句,它包含足够的信息,使得单独指定编码器是多余的)。