Java SparkSession Hive SQL не применяет regexp_replace - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть работающее приложение Spark, выполняющее запросы улья.

С новыми требованиями мне нужно удалить все пробелы из выбранного ключа.

Согласно документации Apache regexp_replace подходит для моего случая:

regexp_replace(string INITIAL_STRING, string PATTERN, string REPLACEMENT) Возвращает строку, полученную в результате замены всех подстрок в INITIAL_STRING, которые соответствуют синтаксису регулярного выражения Java, определенному в PATTERN, экземплярами REPLACEMENT. > Например, regexp_replace("foobar", "oo|ar", "") возвращает 'fb.' Обратите внимание, что при использовании предопределенных классов символов необходимо соблюдать осторожность: использование '\s' в качестве второго аргумента будет соответствовать букве s; '\\s' необходимо для соответствия пробелу и т. Д.

Запуск этого:

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 не был применен. Что может быть причиной этого?

1 Ответ

0 голосов
/ 30 апреля 2018

Первая попытка найти причину состояла в том, чтобы проверить, работает ли запрос в других средах.

Hive Shell вернул ожидаемый результат для select regexp_replace(master_key, '\\s+', '').

\ является escape-символом, и если оболочке куста требуется один escape-символ, использование этого выражения в качестве Java String потребует еще один escape-символ для передачи \ в SparkSession анализатор SQL.

Итак, 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")));
}

Выход:

tet

Чтобы передать \\s+ в синтаксический анализатор SparkSession, нам нужно добавить один экранирующий символ \ на \:

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
...