Есть ли способ просто обрезать столбцы при вставке в Redshift через Glue?

У меня есть столбец, который больше, чем тип данных varchar (max), который, насколько я понимаю, является самым большим типом данных, который использует AWS Glue, и получаю сообщение об ошибке «Длина строки превышает длину DDL», когда я пытаюсь загрузить свои таблицы из-за Это. Я не пытаюсь обрезать этот столбец, потому что он не так уж важен и не могу понять, как это сделать в Glue. Я знаю, что могу использовать TRUNCATECOLUMNS в качестве тега в команде копирования, если я подключаюсь к своей базе данных с помощью psql в экземпляре EC2 и действительно могу успешно загрузить свои таблицы таким образом. Однако мой босс настаивает, чтобы я использовал Glue для этой работы, поэтому я ищу способ обрезать столбцы с помощью скрипта Glue. Я просмотрел много документации, но не нашел ничего похожего. Спасибо.

Вот рабочий код для всех, кто может иметь эту проблему и нуждается в полной справке. Обратите внимание, что varchar(65535) - это максимальное количество символов, которое столбец может быть в Redshift:

val truncColUdf = udf((str: String) => if (str.length > 29999) str.substring(0, 29999) else str)

val datasource30 = glueContext.getCatalogSource(database = "database", tableName = "entry", redshiftTmpDir = "", transformationContext = "datasource30").getDynamicFrame()
val revDF30 = datasource30.toDF()
  .withColumn("message", truncColUdf(col("message")))
val truncDynamicFrame30 = DynamicFrame(revDF30, glueContext)
val applymapping30 = truncDynamicFrame30.applyMapping(mappings = Seq(("id", "bigint", "id", "bigint"), ("message", "string", "message", "varchar(65535)"), ("state", "string", "state", "varchar(256)"), ("created_at", "timestamp", "created_at", "timestamp"), ("depth", "int", "depth", "int")), caseSensitive = false, transformationContext = "applymapping30")
val resolvechoice30 = applymapping30.resolveChoice(choiceOption = Some(ChoiceOption("make_cols")), transformationContext = "resolvechoice30")
val dropnullfields30 = resolvechoice30.dropNulls(transformationContext = "dropnullfields30")
val datasink30 = glueContext.getJDBCSink(catalogConnection = "databaseConnection", options = JsonOptions("""{"dbtable": "entry", "database": "database"}"""), redshiftTmpDir = args("TempDir"), transformationContext = "datasink30").writeDynamicFrame(dropnullfields30)

Вот пример строки считываемых данных:

01,"<p>Here is the message where the quotations are in case of commas within the message, like so.</p>",active,2017-08-27 23:38:40,1

person vtbiggi    schedule 01.08.2018    source источник


Ответы (2)


Преобразуйте DynamicFrame в DataFrame искры, а затем используйте определяемую пользователем функцию для усечения значения столбца (Scala):

import com.amazonaws.services.glue.DynamicFrame
import org.apache.spark.sql.functions._

val truncColUdf = udf((str: String) => if (str.length > 20) str.substring(0, 20) else str)
val truncDataFrame = dynamicFrame.toDF()
  .select("text_long")
  .withColumn("text_short", truncColUdf(col("text_long")))
  .withColumn("text_short_length", length(col("text_short")))

truncDataFrame.show(5, false)

val truncDynamicFrame = DynamicFrame(truncDataFrame, glueContext)

...

//write to sink

Выход:

+-----------------------+--------------------+-----------------+
|text_long              |text_short          |text_short_length|
+-----------------------+--------------------+-----------------+
|I'd rather not answer  |I'd rather not answe|20               |
|Agree                  |Agree               |5                |
|Custom Answer Favorable|Custom Answer Favora|20               |
|Agree                  |Agree               |5                |
|Sometimes              |Sometimes           |9                |
+-----------------------+--------------------+-----------------+
person Yuriy Bondaruk    schedule 03.08.2018
comment
Я получаю сообщение об ошибке, когда запускаю последнюю строку, говоря, что не может найти DynamicFrame. Есть идеи, почему? - person vtbiggi; 03.08.2018
comment
Итак, я понял это, и мой код теперь работает. Все, что мне нужно, это включить import com.amazonaws.services.glue.DynamicFrame в дополнение к тому, что вы ответили. Спасибо! - person vtbiggi; 03.08.2018
comment
Это в некоторой степени работает. Тем не менее, он переводит все на указанную мной длину (65535), хотя я считаю, что следует сохранить более короткие строки на их текущей длине. - person vtbiggi; 19.08.2018
comment
Хммм ... можешь поделиться своим кодом? Кстати, я обновил ответ своим выводом - person Yuriy Bondaruk; 20.08.2018
comment
ОК, код готов. Я также разместил вопрос о проблеме с отметкой времени, если вы заметили что-то неправильное. - person vtbiggi; 20.08.2018
comment
Хорошо, я понял проблему с пробелами. Я считаю, что твой путь сработал правильно, я просто совсем не думал. - person vtbiggi; 20.08.2018

Вы можете передать TRUNCATECOLUMNS в параметре extracopyoptions вашего DynamicFrameWriter: https://aws.amazon.com/premiumsupport/knowledge-center/sql-commands-redshift-glue-job/

person Nadia    schedule 16.06.2021