【问题标题】:Converting cassandra blob type to string将 cassandra blob 类型转换为字符串
【发布时间】:2015-10-27 05:47:56
【问题描述】:

我有一个旧的列族,它有一个名为“value”的列,它被定义为 blob 数据类型。此列通常包含两个用下划线分隔的数字,例如“421_2”。

当我使用 python datastax 驱动程序并执行查询时,结果返回该字段解析为字符串:

In [21]: session.execute(q)
Out[21]: 
[Row(column1=4776015, value='145_0'),
 Row(column1=4891778, value='114_0'),
 Row(column1=4891780, value='195_0'),
 Row(column1=4893662, value='105_0'),
 Row(column1=4893664, value='115_0'),
 Row(column1=4898493, value='168_0'),
 Row(column1=4945162, value='148_0'),
 Row(column1=4945163, value='131_0'),
 Row(column1=4945168, value='125_0'),
 Row(column1=4945169, value='211_0'),
 Row(column1=4998426, value='463_0')]

当我使用 java 驱动程序时,我得到一个 com.datastax.driver.core.Row 对象。例如,当我尝试通过row.getString("value") 读取值字段时,我得到了预期的InvalidTypeException: Column value is of type blob。似乎读取该字段的唯一方法是通过 row.getBytes("value") 然后我得到一个 java.nio.HeapByteBuffer 对象。

问题是,我似乎无法以简单的方式将此对象转换为字符串。谷歌搜索从 2012 年得到了两个答案,表明如下:

String string_value = new String(result.getBytes("value"), "UTF-8");

但是这样的 String 构造函数似乎已经不存在了。 所以,我的问题是:

  1. 如何将 HeapByteBuffer 转换为字符串?
  2. 为什么python驱动很容易转换blob而java没有?

旁注: 我可以调试 python 驱动程序,但目前这对于应该是微不足道的事情来说似乎太多了。 (事实上​​没有人问过这件事表明我在这里遗漏了一些简单的东西..)

【问题讨论】:

    标签: java cassandra blob cql datastax


    【解决方案1】:

    另一种更简单的方法是更改​​ CQL 语句。

    select column1, blobastext(value) from YourTable where key = xxx
    

    第二列是字符串类型。

    【讨论】:

    • 我喜欢这个,但我不确定将它合并到 Java 驱动程序中是否容易......要去检查。
    • 我没有找到一种方法将函数应用于 Datastax 提供的 Java QueryBuilder 对象中的选定列。否则这将是一个非常优雅的解决方案。
    • 为什么不直接使用session.execute("select column, ....")呢?如果您需要使用 QueryBuilder,请尝试Selection.Selection::fcall。我非常确定 blobastext 在 java 驱动程序中工作,因为我在我的生产项目中使用它。
    • 您知道如何以编程方式从字符串创建 blob 吗?出于某种原因,fcall 仅在选择中可用。例如,如果我现在需要更新 blob 列怎么办?
    • @idoda 它应该是 textAsBlob(?)
    【解决方案2】:

    您还可以直接访问 Java 驱动程序的序列化程序。这样您就不必处理低级细节,而且它也适用于其他类型。

    驱动程序 2.0.x:

    String s = (String)DataType.text().deserialize(byteBuffer);
    

    驱动程序 2.1.x:

    ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
    String s = (String)DataType.text().deserialize(byteBuffer, protocolVersion);
    

    驱动程序 2.2.x:

    ProtocolVersion protocolVersion = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
    String s = TypeCodec.VarcharCodec.instance.deserialize(byteBuffer, protocolVersion);
    

    【讨论】:

    • 很好的答案!列出每个驱动程序版本的不同之处也会对其他人有很大帮助。
    • @BryceAtNetwork23 我同意,详细的回答,谢谢 Olivier!
    • 知道是否可以根据 DataType.getType() 动态执行 TypeCodec 吗?我正在尝试将大量使用这种方法的库转换为 2.2。
    • 对 3.0.x 驱动有什么想法吗?你在哪里找到的?
    【解决方案3】:

    对于 3.1.4 版的 datastax java 驱动程序,以下会将 blob 转换为字符串:

    ProtocolVersion proto = cluster.getConfiguration().getProtocolOptions().getProtocolVersion();
    
    String deserialize = TypeCodec.varchar().deserialize(row.getBytes(i), proto);
    

    【讨论】:

      【解决方案4】:

      1.) 在 Java 中从字节缓冲区转换在 this answer 中讨论。

      2.) 假设您使用的是 Python 2,它会在 Python 中以字符串形式返回,因为 str 是二进制类型。

      【讨论】:

        猜你喜欢
        • 2017-11-28
        • 2013-06-28
        • 2020-01-19
        • 2017-07-07
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        • 1970-01-01
        • 2020-05-21
        相关资源
        最近更新 更多