我有一个字段代表我的架构中的IP地址。我想使用Binary Type来存储数据。
我想象的方式是,如果我的ip是:50.100.150.200
我将它保存为[50,100,150,200]
字节数组(序列肯定很重要,但我们可以将其排除在此问题的讨论之外)。
我的问题是如何在查询时按此列进行过滤? (字符串并不真正符合目的)
例如,我想运行以下查询:
SELECT * from table1 WHERE sourceip='50.100.150.200'
以下是一段用于演示此问题的代码:
Bean定义(用于模式创建):
public static class MyBean1 implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private byte[] description;
public MyBean1(int id, String name, String description) {
this.id = id;
this.name = name;
this.description = description.getBytes();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getDescription() {
return description;
}
public void setDescription(byte[] description) {
this.description = description;
}
}
演示代码(我想按说明进行过滤):
List<MyBean1> newDebugData = new ArrayList<MyBean1>();
newDebugData.add(new MyBean1(1, "Arnold", "10.150.15.10"));
newDebugData.add(new MyBean1(1, "Bob", "10.150.15.11"));
newDebugData.add(new MyBean1(3, "Bob", "10.150.15.12"));
newDebugData.add(new MyBean1(3, "Bob", "10.150.15.13"));
newDebugData.add(new MyBean1(1, "Alice", "10.150.15.14"));
Dataset<Row> df2 = sqlContext.createDataFrame(newDebugData, MyBean1.class);
df2.createTempView("table1");
sqlContext.sql("select * from table1 where description='10.150.15.14'").show();
我收到错误:
differing types in '(table1.`description` = CAST('10.150.15.14' AS DOUBLE))'
答案 0 :(得分:0)
这不是你问题的100%答案,但我希望指针有所帮助。
以下问题不是关于过滤,而是选择数组中的数据。 selecting a range of elements in an array spark sql
它看起来像很多信息,包括UDF使用Spark SQL查询数组的一些指导。
希望这有帮助。
答案 1 :(得分:0)
SPARK-21344在版本2.0.3、2.1.2和2.2.1中修复了以下问题:BinaryType比较不会对有符号字节数组进行比较。因此,二进制比较应该适用于这些版本。
JIRA具有以下scala测试代码:
case class TestRecord(col0: Array[Byte])
def convertToBytes(i: Long): Array[Byte] = {
val bb = java.nio.ByteBuffer.allocate(8)
bb.putLong(i)
bb.array
}
val timestamp = 1498772083037L
val data = (timestamp to timestamp + 1000L).map(i => TestRecord(convertToBytes(i)))
val testDF = sc.parallelize(data).toDF
val filter1 = testDF.filter(col("col0") >= convertToBytes(timestamp)
&& col("col0") < convertToBytes(timestamp + 50L))
assert(filter1.count == 50)
我不知道等效的Java代码是什么,但这应该可以帮助您入门。
我在上面的评论中提到我们使用LongType存储IPv4地址的问题。我们有一个包装器脚本,可将点分十进制转换为长整数,而Spark UDF则采用另一种方式:将长整数转换为点分十进制。我认为LongType的查询比BinaryType更快。