Usa JavaScript en Dataform

En este documento, se explica cómo puedes usar JavaScript para desarrollar flujos de trabajo en Dataform. En este documento, también se muestra cómo usar JavaScript para crear acciones de flujo de trabajo y cómo crear inclusiones de JavaScript para reutilizar código en Dataform.

Dataform core te permite crear acciones de flujo de trabajo con SQLX y JavaScript. Si bien es opcional, usar JavaScript junto con SQLX para crear elementos similares de forma repetida en tu flujo de trabajo Por ejemplo, con JavaScript, puedes crear una vista de cada tabla de tu flujo de trabajo con ciertos IDs de usuario quitados. También puedes desarrollar acciones de flujo de trabajo exclusivamente con JavaScript.

Antes de comenzar

  1. En la consola de Google Cloud , ve a la página Dataform.

    Ir a Dataform

  2. Selecciona o crea un repositorio.

  3. Selecciona o crea un lugar de trabajo de desarrollo.

Además, debes conocer la sintaxis de JavaScript y los siguientes conceptos de JavaScript:

  • Variables
  • Arrays
  • Instrucciones condicionales
  • Bucles for
  • Maps
  • Funciones
  • Objetos
  • Cómo importar y exportar módulos

Roles obligatorios

Para obtener los permisos que necesitas para desarrollar un flujo de trabajo con JavaScript y reutilizar código con JavaScript includes, pídele a tu administrador que te otorgue el rol de IAM de Editor de Dataform (roles/dataform.editor) en los espacios de trabajo. Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

Agrega código JavaScript a un archivo SQLX

Puedes agregar código JavaScript a un archivo SQLX de dos maneras: de forma intercalada o dentro de un bloque JavaScript.

Puedes usar un bloque de JavaScript para definir funciones o constantes en un archivo SQLX. Puedes usar JavaScript intercalado para modificar de forma dinámica una consulta de SQLX o SQL.

En el siguiente muestra de código, se muestra la función self integrada de Dataform Core en JavaScript agregada de forma intercalada al bloque post_operations en un archivo SQLX:

config {type: "table"}

SELECT * FROM ...

post_operations {
  GRANT `roles/bigquery.dataViewer`
  ON
  TABLE ${self()}
  TO "group:allusers@example.com", "user:otheruser@example.com"
}

En la siguiente muestra de código, se muestra una constante definida en un bloque de JavaScript y que se usa de forma intercalada dentro de una consulta en un archivo SQLX:

js {
  const columnName = "foo";
}

SELECT 1 AS ${columnName} FROM "..."

Cómo reutilizar código en un solo archivo SQLX con encapsulación de JavaScript

Puedes reutilizar el código de JavaScript para optimizar el desarrollo en Dataform. Para reutilizar constantes y funciones de JavaScript en un solo archivo SQLX, puedes encapsularlas en un bloque de JavaScript. Para reutilizar código JavaScript en un solo repositorio de Dataform, puedes crear archivos de inclusión. Para reutilizar código de JavaScript en varios repositorios de Dataform, puedes crear o importar un paquete.

Para crear partes repetitivas de código SQL que puedas reutilizar en un solo archivo SQLX, puedes encapsular funciones y constantes en un bloque de JavaScript. Solo puedes reutilizar el código definido en un bloque de JavaScript dentro del archivo SQLX en el que se define el bloque. Para obtener más información, consulta Dataform Core.

En el siguiente muestra de código, se muestran una constante y una función definidas en un bloque de JavaScript y que se usan de forma intercalada dentro de una consulta en un archivo SQLX:

js {
 const foo = 1;
 function bar(number){
     return number+1;
 }
}

select
 ${foo} as one,
 ${bar(foo)} as two

Cómo reutilizar código en un solo repositorio con la función de inclusión

Las inclusiones son constantes o funciones de JavaScript globales para tu repositorio. Defines las inclusiones en el directorio includes de tu repositorio. Luego, puedes reutilizarlos en todo tu repositorio en archivos JavaScript y SQLX.

En el siguiente muestra de código, se muestra la definición de la constante launch_date en el archivo includes/constants.js:

// filename is includes/constants.js
const launch_date = "11.11.2011";
module.exports = { launch_date };

En la siguiente muestra de código, se muestra la constante launch_date a la que se hace referencia en una consulta de definición de tabla en un archivo SQLX:

config {type: "table"}

SELECT * FROM source_table WHERE date > ${constants.launch_date}

Crea un archivo JavaScript para las inclusiones

Para crear un archivo JavaScript nuevo en el directorio includes/, sigue estos pasos:

  1. En el panel Archivos, junto a includes/, haz clic en Más.

  2. Haz clic en Crear archivo.

  3. En el panel Crear un archivo nuevo, haz lo siguiente:

    1. En el campo Agregar una ruta de archivo, después de includes/, ingresa el nombre del archivo seguido de .js. Por ejemplo, includes/constants.js.

      Los nombres de archivo solo pueden incluir números, letras, guiones y guiones bajos.

    2. Haz clic en Crear archivo.

Crea una constante de JavaScript

Para crear una constante que puedas reutilizar en todo tu proyecto, sigue estos pasos:

  1. Ve a tu espacio de trabajo de desarrollo.

  2. En el panel Archivos, expande includes/.

  3. Crea o selecciona un archivo JavaScript con la extensión .js.

  4. En el archivo, ingresa el siguiente fragmento de código:

     const CONSTANT_NAME = CONSTANT_VALUE;
     module.exports = { CONSTANT_NAME };
    

    Reemplaza lo siguiente:

    • CONSTANT_NAME: El nombre de tu constante
    • CONSTANT_VALUE: Es el valor de tu constante.
  5. Opcional: Haz clic en Formato.

En el siguiente muestra de código, se define la constante PROJECT_ID en el archivo includes/constants.js:

  // filename is includes/constants.js
  const PROJECT_ID = "my_project_name";
  module.exports = { PROJECT_ID };

En la siguiente muestra de código, se hace referencia a la constante PROJECT_ID en una consulta de definición de tabla en un archivo SQLX:

  config { type: "table" }
  SELECT * FROM ${constants.PROJECT_ID}.my_schema_name.my_table_name

En la siguiente muestra de código, se muestra la consulta de definición de la tabla principal anterior de Dataform compilada en SQL:

  SELECT * FROM my_project_name.my_schema_name.my_table_name

Crea una función de JavaScript personalizada

Para crear una función personalizada de JavaScript que puedas reutilizar en todo tu proyecto, sigue estos pasos:

  1. Ve a tu espacio de trabajo de desarrollo.

  2. En el panel Archivos, expande includes/.

  3. Crea o selecciona un archivo JavaScript con la extensión .js.

  4. En el archivo, escribe tu función de JavaScript personalizada.

  5. En el archivo, ingresa el siguiente fragmento de código:

     module.exports = { FUNCTION_NAME }
    

    Reemplaza FUNCTION_NAME por el nombre de tu función.

  6. Opcional: Haz clic en Formato.

En la siguiente muestra de código, se muestra una función personalizada de JavaScript llamada renderScript y almacenada en el archivo includes/functions.js. La función genera una secuencia de comandos de SQL:

  function renderScript(table, dimensions, metrics) {
    return `
        select
        ${dimensions.map(field => `${field} as ${field}`).join(",")},
        ${metrics.map(field => `sum(${field}) as ${field}`).join(",\n")}
        from ${table}
        group by ${dimensions.map((field, i) => `${i + 1}`).join(", ")}
      `;
  }

  module.exports = { renderScript };

En el siguiente muestra de código, se muestra el uso de la función renderScript personalizada de JavaScript en una consulta de definición de tabla principal de Dataform:

  config {
      type: "table",
      tags: ["advanced", "hourly"],
      disabled: true
  }

  ${functions.renderScript(ref("source_table"),
                                ["country", "device_type"],
                                ["revenue", "pageviews", "sessions"]
                                )}

En la siguiente muestra de código, se muestra la consulta de definición de la tabla principal anterior de Dataform compilada en SQL:

  select
    country as country,
    device_type as device_type,
    sum(revenue) as revenue,
    sum(pageviews) as pageviews,
    sum(sessions) as sessions

  from "dataform"."source_table"

  group by 1, 2

Cómo hacer referencia a un elemento include en un archivo SQLX

Puedes hacer referencia a cualquier función o constante de inclusión dentro de un archivo SQLX. La sintaxis para hacer referencia a las inclusiones depende de la ubicación del archivo de inclusión. Un archivo de inclusión de nivel superior se encuentra directamente en el directorio includes/. Un archivo de inclusión anidado se encuentra en un subdirectorio de includes/.

Cómo hacer referencia a una inclusión de nivel superior en un archivo SQLX

  • Para hacer referencia a una función o constante de inclusión de nivel superior en una consulta principal de Dataform, ingresa el nombre de archivo de la definición de inclusión sin la extensión .js, seguido del nombre del objeto exportado.

La siguiente muestra de código hace referencia a la constante firstDate, definida en el archivo includes/constants.js, en un archivo SQLX de definición de tabla:

  config {type: "table"}
  select * from source_table where date > ${constants.firstDate}

Cómo hacer referencia a una inclusión anidada en un archivo SQLX

Para hacer referencia a las inclusiones ubicadas en subdirectorios de definitions, importa las inclusiones con la función require de JavaScript y un bloque js {}.

Para hacer referencia a una inclusión anidada con la función require de JavaScript, sigue estos pasos:

  1. Ve a tu espacio de trabajo de desarrollo.

  2. En el panel Archivos, expande definitions/.

  3. Selecciona un archivo SQLX.

  4. En el bloque config, ingresa el siguiente fragmento de código:

     js {
       var { VARIABLE_NAME } = require("SUBDIRECTORY_INCLUDE");
     }
    

    Reemplaza lo siguiente:

    • VARIABLE_NAME: Es el nombre de la constante o la función que deseas importar.
    • SUBDIRECTORY_INCLUDE: Es la ruta de acceso del archivo includes anidado.
  5. Opcional: Haz clic en Formato.

La siguiente muestra de código hace referencia a la constante firstDate, definida en el archivo includes/allConstants/constants.js anidado, en un archivo SQLX de definición de tabla:

  config {type: "table"}
  js {
    var { firstDate } = require("includes/allConstants/constants");
  }
  select * from source_table where date > ${firstDate}

Usa una función de inclusión de JavaScript con la función ref de Dataform Core

Para usar una función de inclusión de JavaScript con la función ref de Dataform Core, debes pasar ref como argumento de la función de inclusión de JavaScript dentro de un archivo SQLX.

En la siguiente muestra de código, se muestra el archivo includes/script_builder.js con la función renderScript de JavaScript que agrega métricas con SUM y las agrupa por dimensión:

function renderScript(table, dimensions, metrics) {
  return `
      SELECT
      ${dimensions.map((field) => `${field} AS ${field}`).join(",\\n")},
      ${metrics.map((field) => `SUM(${field}) AS ${field}`).join(",\\n")}
      FROM ${table}
      GROUP BY ${dimensions.map((field, i) => `${i + 1}`).join(", ")}
    `;
}
module.exports = { renderScript };

En la siguiente muestra de código, se muestra la función renderScript de JavaScript que se usa en el archivo definitions/stats_per_country_and_device.sqlx con la función ref principal de Dataform que se pasa como un argumento:

${script_builder.renderScript(
  ref("source_table"),
  ["country", "device_type"],
  ["revenue", "pageviews", "sessions"])}

En el siguiente muestra de código, se muestra la consulta de definitions/stats_per_country_and_device.sqlx compilada en SQL:

SELECT country AS country,
       device_type AS device_type,
       SUM(revenue) AS revenue,
       SUM(pageviews) AS pageviews,
       SUM(sessions) AS sessions
FROM my_schema.source_table
GROUP BY 1, 2

Para obtener más información sobre la función ref principal de Dataform, consulta Dataform Core.

Cómo reutilizar código en varios repositorios con paquetes

Los paquetes son colecciones de código JavaScript que puedes importar y usar en varios repositorios de Dataform para optimizar el desarrollo del flujo de trabajo.

Puedes crear tu propio paquete personalizado en Dataform o usar uno de los paquetes de código abierto de Dataform, disponibles en la página de código abierto de Dataform en GitHub.

Para poder usar el contenido de un paquete en Dataform, debes instalarlo en tu repositorio de Dataform y, luego, importarlo al archivo individual de JavaScript o SQLX en el que quieras usarlo. Para obtener más información, consulta Cómo instalar un paquete.

Para poder instalar un paquete privado de NPM en un repositorio de Dataform, debes autenticar el paquete.

Crea flujos de trabajo exclusivamente con JavaScript

En esta sección, se muestra cómo usar JavaScript para crear acciones de flujo de trabajo en Dataform. Es posible que desees usar JavaScript en lugar de Dataform Core para crear elementos similares de forma repetida en tu flujo de trabajo.

Como alternativa al desarrollo de flujos de trabajo en SQLX, o SQLX combinado con JavaScript, puedes crear acciones de flujo de trabajo en archivos .js usando solo JavaScript. Puedes crear varias acciones de flujo de trabajo en un archivo JavaScript con métodos globales de Dataform y código JavaScript ES5 arbitrario, como bucles y constantes. Cada uno de los métodos globales de JavaScript de Dataform contiene propiedades que puedes usar para configurar los objetos creados.

Puedes crear las siguientes acciones de flujo de trabajo solo con JavaScript en Dataform:

  • Declaraciones de fuentes de datos
  • Tablas
  • Aserciones manuales
  • Operaciones de SQL personalizadas

Con JavaScript, puedes crear acciones similares de forma repetida en tu flujo de trabajo. Por ejemplo, puedes crear una vista de cada tabla de tu flujo de trabajo con ciertos IDs de usuario quitados.

En el siguiente muestra de código JavaScript, se muestra cómo crear una vista de cada tabla en la que el valor del campo user_id no corresponde a uno de los valores de la lista blocked_user_ids:

  const tableNames = ["user_events", "user_settings", "user_logs"];

  tableNames.forEach(tableName => {
    publish(tableName + "_blocked_removed").query(
      ctx => `
        SELECT * FROM ${ctx.ref(tableName)}
        WHERE user_id NOT IN (
          SELECT user_id
          FROM ${ctx.ref("blocked_user_ids")}
        )`
    );
  });

En esta muestra de código, se crean tres vistas llamadas user_events_blocked_removed, user_settings_blocked_removed y user_logs_blocked_removed que no contienen ninguno de los IDs de usuario bloqueados.

Puedes crear varias acciones en un archivo JavaScript con métodos globales de Dataform y código JavaScript ES5 arbitrario, como bucles y constantes.

Puedes definir las siguientes acciones con JavaScript en Dataform:

Crea un archivo JavaScript

Almacena los archivos JavaScript para las declaraciones de definiciones y fuentes de datos en el directorio definitions/. Para crear un archivo JavaScript nuevo en el directorio definitions/, sigue estos pasos:

  1. En el panel Archivos, junto a definitions/, haz clic en Más.

  2. Haz clic en Crear archivo.

  3. En el panel Crear un archivo nuevo, haz lo siguiente:

    1. En el campo Agregar una ruta de archivo, después de definitions/, ingresa el nombre del archivo seguido de .js. Por ejemplo, definitions/definitions.js

      Los nombres de archivo solo pueden incluir números, letras, guiones y guiones bajos.

    2. Haz clic en Crear archivo.

Cómo establecer propiedades de acciones de flujo de trabajo con JavaScript

Puedes usar los siguientes métodos globales de Dataform para crear acciones de flujo de trabajo de SQL con Dataform:

  • declare: Se usa para declarar una fuente de datos.
  • publish: Se usa para definir una tabla.
  • assert: Se usa para crear una aserción.
  • operate: Se usa para definir una operación de SQL personalizada.

Cada uno de los métodos globales contiene propiedades que puedes usar para configurar el objeto creado. Para obtener más información sobre los métodos globales y sus propiedades, consulta la referencia principal de Dataform.

En el método publish() que crea una tabla, puedes establecer propiedades de la tabla pasándolas como el segundo argumento del método.

Para pasar propiedades de la tabla como el segundo argumento de publish(), sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, agrega propiedades de la tabla al método publish() con el siguiente formato:

     method("first_method_argument", {
       property1: "property1_value",
       property2: "property2_value",
       property3: "property3_value",
     });
    
  4. Opcional: Haz clic en Formato.

En el siguiente muestra de código, se muestra cómo establecer propiedades en el método publish() pasando las propiedades como segundo argumento del método:

  publish("table1", {
    type: "table",
    dependencies: ["other_table"],
    description: {
      "Value is 1"
    }
  }).query(ctx => "SELECT 1 AS test");

Referencia a las inclusiones en un archivo JavaScript

Puedes hacer referencia a cualquier función, macro o constante de inclusión dentro de un archivo JavaScript. Para obtener más información sobre las instrucciones include en Dataform, consulta la sección Cómo reutilizar código en un solo repositorio con instrucciones include de este documento.

La sintaxis para hacer referencia a las inclusiones dentro de un archivo JavaScript depende de la ubicación del archivo de inclusión. Dataform almacena estos archivos en el directorio includes.

Las referencias de nivel superior incluyen

  • Para hacer referencia a un archivo de inclusión de nivel superior, haz referencia al nombre del archivo cuando declares tus variables.

En la siguiente muestra de código, se hace referencia a las variables serviceName y serviceId del archivo includes/service.js:

  const {serviceName, serviceId} = service;

Referencia a inclusiones anidadas

Para hacer referencia a un archivo de inclusión anidado, ingresa el nombre del archivo en la función require de JavaScript.

En la siguiente muestra de código, se hace referencia a las variables serviceName y serviceId del archivo includes/allServices/service.js:

  const {serviceName, serviceId} = require("includes/allServices/service.js");

Usa funciones de consulta de Dataform en métodos de JavaScript

Dataform proporciona varias funciones integradas que puedes usar en las consultas, como ref y self. Para obtener más información sobre las funciones integradas de Dataform, consulta la referencia de la API de Dataform.

Para usar una función de consulta integrada en un método de JavaScript, sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, ingresa un método global de JavaScript de Dataform.

  4. En el método, ingresa un argumento ctx que se pueda contextualizar.

  5. Opcional: Si usas cadenas de plantilla de JavaScript, incluye el argumento contextualizable entre comillas inversas ``.

  6. En el argumento contextable, ingresa la función de consulta con su parámetro como un objeto de contexto.

  7. Opcional: Haz clic en Formato.

En la siguiente muestra de código, se muestra la función de consulta ref incluida en un argumento contextual del método de publicación:

  publish("example").query(ctx => `SELECT * FROM ${ctx.ref("other_table")}`);

Cómo declarar una fuente de datos de flujo de trabajo con JavaScript

Puedes declarar varias fuentes de datos en un archivo de declaración de JavaScript con el método de declaración de JavaScript de Dataform. Para obtener más información sobre el método declare, consulta la referencia principal de Dataform. Para obtener más información sobre las fuentes de datos en Dataform, consulta Cómo declarar una fuente de datos.

Para declarar una fuente de datos en un archivo JavaScript, sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, ingresa el siguiente fragmento de código:

     declare({
       database: "DATABASE_PROJECT_ID",
       schema: "BIGQUERY_SCHEMA",
       name: "RELATION_NAME",
     });
    

    Reemplaza lo siguiente:

    • DATABASE_PROJECT_ID: Es el ID del proyecto que contiene la fuente de datos.
    • BIGQUERY_SCHEMA: Es el conjunto de datos de BigQuery en el que existe la relación externa.
    • RELATION_NAME: Es el nombre de la relación que puedes usar más adelante para hacer referencia a la fuente de datos en Dataform.
  4. Para declarar otra fuente de datos en el mismo archivo, agrega un bloque declare adicional al archivo.

  5. Opcional: Haz clic en Formato.

Cómo definir una tabla con JavaScript

Puedes crear una tabla con el método publish de JavaScript de Dataform. Para obtener más información sobre el método publish, consulta la referencia principal de Dataform.

Puedes definir los siguientes tipos de tablas:

  • Tabla
  • Tabla incremental
  • Ver

Para obtener más información sobre cómo definir tablas en Dataform, consulta Crea tablas.

Para definir una tabla en un archivo JavaScript, sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, ingresa el siguiente fragmento de código:

     publish("TABLE_NAME").query(ctx => "SELECT_QUERY");
    

    Reemplaza lo siguiente:

    • TABLE_NAME: El nombre de la tabla.
    • SELECT_QUERY: Es una sentencia SELECT de SQL que define la tabla.
  4. Para establecer el tipo de tabla, agregar dependencias de tabla y agregar una descripción de la tabla, establece las propiedades del objeto del método publish.

  5. Para definir otra tabla en el mismo archivo, repite los pasos 3 y 4.

  6. Opcional: Haz clic en Formato.

Cómo definir aserciones manuales con JavaScript

Puedes crear aserciones de SQL manuales en un archivo JavaScript con el método assert de JavaScript de Dataform. Para obtener más información sobre el método assert, consulta la referencia principal de Dataform.

Una consulta en SQL de aserción manual debe devolver cero filas. Si la consulta devuelve filas cuando se ejecuta, la aserción falla. Puedes crear varias aserciones en un archivo JavaScript.

Para obtener más información sobre las aserciones en Dataform, consulta Prueba la calidad de los datos.

Para crear una aserción manual en un archivo JavaScript, sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, ingresa el siguiente fragmento de código:

     assert("ASSERTION_NAME").query(ctx => "CUSTOM_ASSERTION_QUERY");
    

    Reemplaza lo siguiente:

    • ASSERTION_NAME: El nombre de tu aserción personalizada
    • CUSTOM_ASSERTION_QUERY: Tu consulta de aserción de SQL
  4. Para crear otra aserción en el mismo archivo, repite el paso 3.

  5. Opcional: Haz clic en Formato.

En la siguiente muestra de código, se muestra una aserción de JavaScript que confirma que ningún valor en source_table es NULL:

  assert("assertion1").query(ctx => "SELECT * FROM source_table WHERE value IS NULL");

Cómo definir operaciones de SQL personalizadas con JavaScript

Puedes definir operaciones de SQL personalizadas en un archivo JavaScript con el método operate de JavaScript de Dataform. Para obtener más información sobre las operaciones de SQL personalizadas en Dataform, consulta Crea operaciones.

Para definir una operación en SQL personalizada con JavaScript, sigue estos pasos:

  1. En el espacio de trabajo de desarrollo, en el panel Files, expande definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, ingresa el siguiente fragmento de código:

     operate("OPERATION_NAME").queries(ctx => "CUSTOM_SQL_QUERY");
    

    Reemplaza lo siguiente:

    • OPERATION_NAME: Es el nombre de la operación personalizada.
    • CUSTOM_SQL_QUERY: Tu consulta en SQL personalizada
  4. Para definir otra operación de SQL personalizada en el mismo archivo, repite el paso 3.

  5. Opcional: Haz clic en Formato.

En el siguiente muestra de código, se muestra una operación SQL personalizada en un archivo JavaScript que inserta una sola fila nueva en some_table y establece test_column de la fila nueva en 2:

  operate("operation1").queries("INSERT INTO some_table (test_column) VALUES (2)");

¿Qué sigue?