У меня есть работающее приложение Spark, выполняющее запросы кустов.
С новыми требованиями мне нужно удалить все пробелы из выбранного ключа.
По Документация Apache для моего случая подходит regexp_replace:
regexp_replace(string INITIAL_STRING, string PATTERN, string REPLACEMENT)Returns the string resulting from replacing all substrings in INITIAL_STRING that match the java regular expression syntax defined in PATTERN with instances of REPLACEMENT. > For example,regexp_replace("foobar", "oo|ar", "")returns'fb.'Note that some care is necessary in using predefined character classes: using'\s'as the second argument will match the letter s;'\\s'is necessary to match whitespace, etc.
Запускаем это:
public class SparkSql {
private SparkSession session = SparkSession.builder()
.appName("hive-sql")
.config("spark.config.option", "configuration")
.enableHiveSupport()
.getOrCreate();
// Omitted code here ...
public void execute() {
Dataset<Row> dataset = session.sql("select regexp_replace(master_key, '\\s+', ''") as key from master_table);
JavaRDD<Row> rdd = context.parallelize(dataset.collectAsList(), factor);
for (Row row : rdd.collect())
System.out.println(row.getString(row.fieldIndex("key")));
}
}
Выход:
ABCD 100000
Ожидал:
ABCD100000
Почему-то regexp_replace не применялся.
Что могло быть причиной этого?




Первая попытка найти причину заключалась в том, чтобы проверить, можно ли выполнить запрос в других средах.
Hive Shell вернула ожидаемый результат для select regexp_replace(master_key, '\\s+', '').
\ - это escape-символ, и если оболочке улья требуется один escape-символ, при использовании этого выражения, поскольку Java String потребует еще один escape-символ для передачи \ в синтаксический анализатор SQL SparkSession.
Итак, этот Dataset<Row> dataset = session.sql("select regexp_replace(master_key, '\\s+', ''") as key from master_table); фактически передаст \s+ синтаксическому анализатору SQL:
public void execute() {
Dataset<Row> dataset = session.sql("select regexp_replace("test", '\\s+', ''") as key from master_table);
JavaRDD<Row> rdd = context.parallelize(dataset.collectAsList(), factor);
for (Row row : rdd.collect())
System.out.println(row.getString(row.fieldIndex("key")));
}
Выход:
test
Чтобы передать \\s+ в синтаксический анализатор SQL SparkSession, нам нужно добавить один escape-символ \ для каждого \:
public void execute() {
Dataset<Row> dataset = session.sql("select regexp_replace(master_key, '\\\\s+', ''") as key from master_table);
JavaRDD<Row> rdd = context.parallelize(dataset.collectAsList(), factor);
for (Row row : rdd.collect())
System.out.println(row.getString(row.fieldIndex("key")));
}
Выход:
ABCD100000