Usar 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 explica 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. Aunque es opcional, puedes usar JavaScript junto con SQLX para crear elementos similares repetidamente en tu flujo de trabajo. Por ejemplo, con JavaScript puede crear una vista de cada tabla de su flujo de trabajo con determinados IDs de usuario eliminados. También puedes desarrollar acciones de flujo de trabajo exclusivamente con JavaScript.

Antes de empezar

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

    Ir a Dataform

  2. Seleccione o cree un repositorio.

  3. Seleccione o cree un espacio de trabajo de desarrollo.

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

  • Variables
  • Matrices
  • Instrucciones condicionales
  • Bucles for
  • Maps
  • Functions
  • Objetos
  • Exportar e importar módulos

Roles obligatorios

Para obtener los permisos que necesitas para desarrollar un flujo de trabajo con JavaScript y reutilizar código con las inclusiones de JavaScript, pide a tu administrador que te conceda el rol de gestión de identidades y accesos Editor de Dataform (roles/dataform.editor) en los espacios de trabajo. Para obtener más información sobre cómo conceder roles, consulta el artículo Gestionar el acceso a proyectos, carpetas y organizaciones.

También puedes conseguir los permisos necesarios a través de roles personalizados u otros roles predefinidos.

Añadir código JavaScript a un archivo SQLX

Puedes añadir código JavaScript a un archivo SQLX de dos formas: insertándolo directamente o dentro de un bloque de JavaScript.

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

En el siguiente ejemplo de código se muestra la función de JavaScript self integrada en el núcleo de Dataform, que se ha añadido en línea al bloque post_operations de 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 el siguiente ejemplo de código se muestra una constante definida en un bloque de JavaScript y usada de forma insertada en una consulta de un archivo SQLX:

js {
  const columnName = "foo";
}

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

Reutilizar código en un solo archivo SQLX con encapsulación de JavaScript

Puedes reutilizar código JavaScript para agilizar el desarrollo en Dataform. Para reutilizar constantes y funciones de JavaScript en un mismo archivo SQLX, puedes encapsularlas en un bloque de JavaScript. Para reutilizar código JavaScript en un mismo repositorio de Dataform, puedes crear archivos de inclusión. Para reutilizar código 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 ejemplo de código se muestra una constante y una función definidas en un bloque de JavaScript y usadas de forma insertada en una consulta de un archivo SQLX:

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

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

Reutilizar código en un solo repositorio con includes

Las inclusiones son constantes o funciones de JavaScript globales en tu repositorio. Los archivos de inclusión se definen en el directorio includes de tu repositorio. Después, puedes reutilizarlos en todo tu repositorio en archivos JavaScript y SQLX.

En el siguiente código de ejemplo 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 el siguiente ejemplo 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}

Crear un archivo JavaScript para las inclusiones

Para crear un archivo JavaScript 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 archivo, haz lo siguiente:

    1. En el campo Añadir una ruta de archivo, después de includes/, introduce 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.

Crear una constante de JavaScript

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

  1. Ve a tu espacio de desarrollo.

  2. En el panel Archivos, despliega includes/.

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

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

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

    Haz los cambios siguientes:

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

El siguiente código de ejemplo 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 el siguiente ejemplo de código se hace referencia a la constante PROJECT_ID en una consulta de definición de tabla de un archivo SQLX:

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

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

  SELECT * FROM my_project_name.my_schema_name.my_table_name

Crear una función de JavaScript personalizada

Para crear una función de JavaScript personalizada que pueda reutilizar en todo su proyecto, siga estos pasos:

  1. Ve a tu espacio de desarrollo.

  2. En el panel Archivos, despliega 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, introduce el siguiente fragmento de código:

     module.exports = { FUNCTION_NAME }
    

    Sustituye FUNCTION_NAME por el nombre de tu función.

  6. Opcional: Haz clic en Formato.

En el siguiente ejemplo de código se muestra una función de JavaScript personalizada llamada renderScript que se almacena en el archivo includes/functions.js. La función genera una secuencia de comandos 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 ejemplo de código se muestra el uso de la función de JavaScript renderScript personalizada 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 el siguiente ejemplo de código se muestra la consulta de definición de la tabla principal de Dataform anterior 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

Hacer referencia a una inclusión en un archivo SQLX

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

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, introduce el nombre del archivo de definición de inclusión sin la extensión .js, seguido del nombre del objeto exportado.

El siguiente código de ejemplo 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}

Hacer referencia a una inclusión anidada en un archivo SQLX

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

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

  1. Ve a tu espacio de desarrollo.

  2. En el panel Archivos, despliega definitions/.

  3. Selecciona un archivo SQLX.

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

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

    Haz los cambios siguientes:

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

En el siguiente ejemplo de código se 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}

Usar una función de inclusión de JavaScript con la función ref principal de Dataform

Para usar una función de inclusión de JavaScript con la función ref principal de Dataform, debes enviar ref como argumento de la función de inclusión de JavaScript en un archivo SQLX.

En el siguiente ejemplo de código se muestra el archivo includes/script_builder.js con la función JavaScript renderScript, que agrega métricas mediante 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 el siguiente ejemplo de código se muestra la función JavaScript renderScript que se usa en el archivo definitions/stats_per_country_and_device.sqlx con la función ref principal de Dataform pasada como argumento:

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

En el siguiente código de ejemplo se muestra la consulta 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.

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 Dataform de código abierto, 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, a continuación, importarlo al archivo JavaScript o SQLX en el que quieras usarlo. Para obtener más información, consulta Instalar un paquete.

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

Crear 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. Puede que quieras usar JavaScript en lugar de Dataform Core para crear elementos similares repetidamente en tu flujo de trabajo.

Como alternativa a desarrollar flujos de trabajo en SQLX o en 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 puede usar para configurar los objetos creados.

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

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

Con JavaScript, puedes crear acciones similares repetidamente en tu flujo de trabajo. Por ejemplo, puede crear una vista de cada tabla de su flujo de trabajo con determinados IDs de usuario eliminados.

El siguiente ejemplo de código JavaScript le permite 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")}
        )`
    );
  });

Este código de ejemplo crea 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.

Puede definir las siguientes acciones con JavaScript en Dataform:

Crear un archivo JavaScript

Almacena los archivos JavaScript de las definiciones y las declaraciones de fuentes de datos en el directorio definitions/. Para crear un archivo JavaScript 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 archivo, haz lo siguiente:

    1. En el campo Añadir una ruta de archivo, después de definitions/, introduce 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.

Definir 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 SQL personalizada.

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

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

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

  1. En tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

  3. En el archivo, añade propiedades de 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 ejemplo de código se muestra cómo definir 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");

Incluir referencias en un archivo JavaScript

Puede hacer referencia a cualquier función, macro o constante de inclusión en un archivo JavaScript. Para obtener más información sobre las inclusiones en Dataform, consulta la sección Reutilizar código en un mismo repositorio con inclusiones de este documento.

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

Referencia a las inclusiones de nivel superior

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

En el siguiente código de ejemplo 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, introduce el nombre del archivo en la función require de JavaScript.

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

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

Usar 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, consulte 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 tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

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

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

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

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

  7. Opcional: Haz clic en Formato.

En el siguiente código de ejemplo se muestra la función de consulta ref envuelta en un argumento de contexto del método de publicación:

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

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 JavaScript declare de Dataform. Para obtener más información sobre el método declare, consulta la referencia de Dataform Core. Para obtener más información sobre las fuentes de datos en Dataform, consulta Declarar una fuente de datos.

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

  1. En tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

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

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

    Haz los cambios siguientes:

    • DATABASE_PROJECT_ID: el ID del proyecto que contiene la fuente de datos.
    • BIGQUERY_SCHEMA: el conjunto de datos de BigQuery en el que se encuentra la relación externa
    • RELATION_NAME: 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, añade un bloque declare adicional al archivo.

  5. Opcional: Haz clic en Formato.

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 de Dataform Core.

Puede definir los siguientes tipos de tablas:

  • Tabla
  • Tabla incremental
  • Ver

Para obtener más información sobre cómo definir tablas en Dataform, consulta el artículo Crear tablas.

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

  1. En tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

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

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

    Haz los cambios siguientes:

    • TABLE_NAME: el nombre de la tabla
    • SELECT_QUERY: instrucción SQL SELECT que define la tabla.
  4. Para definir el tipo de tabla, añadir dependencias de tabla y añadir una descripción de la tabla, define 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.

Definir aserciones manuales con JavaScript

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

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

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

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

  1. En tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

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

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

    Haz los cambios siguientes:

    • ASSERTION_NAME: el nombre de la 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 el siguiente ejemplo de código se muestra una aserción de JavaScript que afirma que ningún valor de source_table es NULL:

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

Definir operaciones SQL personalizadas con JavaScript

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

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

  1. En tu espacio de trabajo de desarrollo, en el panel Archivos, despliega definitions/.

  2. Selecciona un archivo JavaScript.

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

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

    Haz los cambios siguientes:

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

  5. Opcional: Haz clic en Formato.

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

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

Siguientes pasos