Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 与Hive的find_in_set函数(不注册临时视图)等效的是什么?_Apache Spark_Apache Spark Sql - Fatal编程技术网

Apache spark 与Hive的find_in_set函数(不注册临时视图)等效的是什么?

Apache spark 与Hive的find_in_set函数(不注册临时视图)等效的是什么?,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,dataframe下面有2列 用户id 用户id列表数组 要求是在用户id列表中查找用户id的位置 样本记录: user_id = x1 user_id_list = ('X2','X1','X3','X6') 结果: postition = 2 我需要第三列的数据框,它在列表中的位置是用户id 结果数据帧列: 用户id 用户id列表 位置 在使用createOrReplaceTempView将数据帧注册为视图之后,我可以使用find_in_set hive函数实现这一点 spark中是否有

dataframe下面有2列

用户id 用户id列表数组 要求是在用户id列表中查找用户id的位置

样本记录:

user_id = x1
user_id_list = ('X2','X1','X3','X6')
结果:

postition = 2
我需要第三列的数据框,它在列表中的位置是用户id

结果数据帧列:

用户id 用户id列表 位置 在使用createOrReplaceTempView将数据帧注册为视图之后,我可以使用find_in_set hive函数实现这一点


spark中是否有sql函数可以在不注册视图的情况下完成此操作?

我不知道这样的函数是spark sql API。有一个函数可以查找数组是否包含名为array_contains的值,但这不是您需要的

您可以使用posexplode将数组分解为具有位置的行,然后按其进行过滤,如:dataframe。选择$id,posexplode$ids。过滤器$id===$col.select$id,$pos。根据用户id列表的长度,它可能不是最佳解决方案。目前,对于版本2.1.1,Spark没有进行优化,以直接数组查找替换上述代码-它将生成行并根据行进行过滤

还要考虑到这种方法将过滤掉用户id不在用户id列表中的任何行,因此您可能需要付出额外的努力来克服这一问题


我建议实现UDF,它正好满足您的需要。缺点:Spark无法查看UDF,因此必须将数据反序列化到Java对象并返回

我的建议是实施一个UDF,就像尤拉提到的那样。下面是一个简短的示例,展示了它的外观:

val spark = SparkSession.builder.getOrCreate()
import spark.implicits._

val df = List((1, Array(2, 3, 1)), (2, Array(1, 2,3))).toDF("user_id","user_id_list")
df.show

+-------+------------+
|user_id|user_id_list|
+-------+------------+
|      1|   [2, 3, 1]|
|      2|   [1, 2, 3]|
+-------+------------+

val findPosition = udf((user_id: Int, user_id_list: Seq[Int]) => {
  user_id_list.indexOf(user_id)    
})

val df2 = df.withColumn("position", findPosition($"user_id", $"user_id_list"))
df2.show

+-------+------------+--------+
|user_id|user_id_list|position|
+-------+------------+--------+
|      1|   [2, 3, 1]|       2|
|      2|   [1, 2, 3]|       1|
+-------+------------+--------+
spark中是否有sql函数可以在不注册视图的情况下完成此操作

不,但也不必注册数据帧来使用find_in_set

expr函数与find_in_set 您可以使用expr函数临时切换到SQL模式,而不是查看对象:

将表达式字符串解析为它表示的列

posexplode函数 您还可以使用posexplode函数from object,它为您节省了一些Scala自定义编码,并且比强制将内部二进制行反序列化为JVM对象的udf优化得更好

scala> users.
  select('*, posexplode($"user_id_list")).
  filter(lower($"user_id") === lower($"col")).
  select($"user_id", $"user_id_list", $"pos" as "position").
  show
+-------+----------------+--------+
|user_id|    user_id_list|position|
+-------+----------------+--------+
|     x1|[X2, X1, X3, X6]|       1|
+-------+----------------+--------+

如果您只需要RDD中某个特定元素的索引,可以尝试这里建议的方法:您能详细说明一下您可能猜到的次优方法吗。?我们不知道user\u id\u列表可以有多长,它本机支持优化。UDFs添加了序列化-反序列化层。您是正确的,这取决于用户\u id\u列表的长度。一方面,posexplode将为用户id列表中的每个元素生成一行;另一方面,它是本机支持的,可能是优化的主题。让我更新我的答案,以便更准确,谢谢。我认为只有在我们比较每个解决方案的执行计划并运行一些性能基准之后,才能给出正确的答案。是否要对您的解决方案进行基准测试?
scala> users.
  select('*, posexplode($"user_id_list")).
  filter(lower($"user_id") === lower($"col")).
  select($"user_id", $"user_id_list", $"pos" as "position").
  show
+-------+----------------+--------+
|user_id|    user_id_list|position|
+-------+----------------+--------+
|     x1|[X2, X1, X3, X6]|       1|
+-------+----------------+--------+