La guia de platanus
  • README
  • Acuerdos
    • Guía de Estilo
      • Ejemplo: Módulo para variables de entorno
  • Stack
    • Getting Started
    • Nuestro MVC extendido
    • Ruby/Rails
      • Power Types
        • General
        • Patrones
          • Commands
          • Utils
          • Services
          • Values
          • Observers
      • Potassium
      • Power API
      • Active Admin
        • General
        • Active Admin Addons
      • Pundit
      • Shrine
        • General
        • Manejo y procesamiento de imágenes
      • Pry
      • Strong Migrations
      • Data Migrate
      • Active Job
      • Gems
      • Engines - Modularización en Rails
    • JavaScript
      • Vue
        • General
        • Testing
      • AlpineJS
    • CSS
    • Mobile
      • Expo
      • React Navigation
      • Redux
        • Crear y conectar una slice en Redux
      • Styling
        • Usando Tailwind en React Native
      • Recursos
    • Resolviendo problemas (debugging)
    • Machine Learning
  • Setup
    • Configuración de tu entorno local
      • Instalación Base
        • OSX
        • Windows
        • Linux
      • Tecnologías
        • Ruby
        • Docker
        • Node
      • Herramientas
        • Linters
        • Editores
          • IDE/Editores de Código
            • Visual Studio Code
            • Sublime Text
        • Git
    • Configuración de proyectos
      • Getting Started
      • Heroku
      • Rails
      • Circle CI
      • Vue
      • Apple App Store
      • Google Play
      • Expo
      • S3
      • Git
      • Cloudflare
      • Sendgrid
      • Dominio + Mailing
      • Google Tag Manager, Analytics, Search Console, etc.
        • Google Tag Manager
          • Configurar Google Tag Manager
        • Google Analytics
        • Indexación en Google
        • Google Ads
      • Crear un bucket de S3
      • SlackBot
      • Google BigQuery
  • Deployment
    • Rails
    • Ruby Gems
    • Browser and Node (Open Source)
    • Mobile
      • Mobile Resources
      • Apple App Storage
      • Google Play
  • Upgrades
    • Upgrade de Vue 2 a Vue 3
    • Migración Hound → reviewdog
    • Upgrade de Postgresql
Con tecnología de GitBook
En esta página
  • ¿Cuando/por qué usar BigQuery?
  • ¿Cómo la usamos?
  • Instalación
  • Uso básico
  • Ejemplo
  • Recursos útiles
  1. Setup
  2. Configuración de proyectos

Google BigQuery

AnteriorSlackBotSiguienteRails

Última actualización hace 2 años

Google BigQuery es un *serverless. *En esencia, es una base de datos SQL, externa a la infraestructura que se suele llevar en nuestros proyectos, y está diseñado para funcionar con grandes volúmenes de datos. Sus integraciones son súper sencillas, por lo que permite tener soluciones para analytics rápidamente.

¿Cuando/por qué usar BigQuery?

Podríamos considerar usar BigQuery en un proyecto en los siguientes casos:

  • Se tiene mucha información transaccional, a la que se quiere tener acceso para hacer analytics.

  • Se quieren aprovechar herramientas que tengan una fácil integración con big query (como data studio)

  • Se quiere evitar sobrecargar la base de datos operacional con consultas para analytics que pueden ser pesadas.

  • Si el producto es B2B podría ser buena idea tener una base de datos individual para cada cliente, que incluya la información relacionada con su empresa y se le pueda facilitar al cliente para que pueda integrar con las herramientas de BI que estime convenientes.

Esto ya que las ventajas de usar Google BigQuery son:

  • Manejar grandes volúmenes de datos con alta velocidad.

  • Acceder a una interfaz en la consola de Google Cloud que permite hacer consultas usando SQL

  • Integrarse con herramientas de analytics y BI de manera sencilla (como por ejemplo Google DataStudio).

  • Al utilizar una base de datos externa para analytics podemos evitar la carga que implicaría sobre nuestra base de datos en heroku las consultas que se requieran para obtener estadísticas más complejas.

¿Cómo la usamos?

Instalación

  1. Creación de un proyecto en la consola de Google Cloud

El primer paso para integrarse con BigQuery es tener un proyecto creado en la consola de Google Cloud.

https://cloud.google.com/resource-manager/docs/creating-managing-projects

  1. Creación de credenciales para acceder a BigQuery via api.

Para usar la gema de BigQuery, necesitaremos una serie de credenciales que se generan creando una *Service Account *en google cloud. Debemos asegurarnos de darle permisos de BigQuery a la cuenta de servicio creada.

https://cloud.google.com/iam/docs/creating-managing-service-accounts

Posteriormente, debemos generar una key nueva para esa cuenta de servicio. Debe ser una key de tipo JSON.

https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating

Con estos pasos, estamos listos para comenzar a configurar BigQuery en nuestro proyecto de rails.

Uso básico

Setup de la gema

Debemos agregar la gema google-cloud-bigquery al gemfile.

Esta gema, automáticamente obtiene las credenciales de una variable de entorno llamada BIGQUERY_CREDENTIALS, por lo que para usarla debemos agregar esa variable, cuyo valor tiene que ser la key que descargamos en el archivo JSON.

Debe verse algo así:

BIGQUERY_CREDENTIALS={"type": "service_account", "project_id": "super-proyecto-genial", "private_key_id": "some_id", "private_key": "some_private_key","client_email": "some_email","client_id": "some_id","auth_uri": "https://accounts.google.com/o/oauth2/auth","token_uri": "https://oauth2.googleapis.com/token","auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url": "some_cert_url"}

En el lugar donde se va a usar la gema (probablemente un client), se debe hacer un require 'google/cloud/bigquery' y crear un objeto Google::Cloud::Bigquery.new. Esto obtiene las credenciales definidas en la variable de entorno automáticamente.

Tipos de recursos

En BigQuery manejaremos principalmente 2 tipos de recursos, datasets y tablas.

Un dataset esta contenido dentro de un proyecto (el que usamos se define por las credenciales), y se usa para organizar y controlar acceso a tablas y vistas.

Una tabla es lo que contiene las filas de datos que le enviaremos a BigQuery, siempre está contenido dentro de un dataset.

Dependiendo del uso, podemos tener múltiples datasets, un solo dataset, múltiples tablas o una sola tabla.

https://cloud.google.com/ruby/docs/reference/google-cloud-bigquery/latest/index.html#creating-datasets-and-tables

En BigQuery no se busca mantener un esquema de base de datos que replique exactamente la que tenemos en nuestro servidor. Esto es porque las bondades de BigQuery son mejor aprovechadas si los datos con los que trabajamos están denormalizados.

Ejemplo

En nuestros proyectos probablemente vamos a tener un cliente, un módulo de util que nos permita conocer el schema de la tabla y cómo desnormalizar un record, y unos cuantos jobs para la creación de datasets, creación de tablas e inserción de datos. Además, necesitaremos agregar un callback al observer del modelo que queremos registrar en bigquery.

💡 Para los siguientes ejemplos, supongamos que tenemos una app para realizar encuestas de cualquier tipo.

Queremos tener una tabla para registrar la información de las respuestas, incluyendo la respuesta misma, la pregunta respondida, la encuesta asociada e información del usuario que responde.

Queremos que esto ocurra cada vez que se crea una nueva respuesta.

Tenemos las siguientes asociaciones entre modelos de nuestra app.

<img src='assets/google-bigquery-1.png'/>

Cliente

# /app/clients/google_bigquery_client.rb
require 'google/cloud/bigquery'

class GoogleBigqueryClient
  def create_dataset(dataset_name)
    client.create_dataset(dataset_name)
  end

  def delete_dataset(dataset_name)
    dataset = client.dataset(dataset_name)
    dataset.delete
  end

  def create_table(dataset_name, table_name, schema)
    dataset = client.dataset(dataset_name)
    dataset.create_table table_name do |table|
      table.name = table_name
      table.description = "Table for #{table_name}"
      table.schema do |s|
        schema.each do |column|
          s.send(column[:type], column[:name], mode: column[:mode])
        end
      end
    end
  end

  def insert_row(dataset_name, table_name, row)
    dataset = client.dataset(dataset_name)
    table = dataset.table(table_name)
    table.insert(row)
  end

  private

  def client
    @client ||= Google::Cloud::Bigquery.new
  end
end

**Módulo para mantener el schema y obtener los atributos de cada **Answer

# app/utils/answers_data.rb
module AnswersData
  def self.attributes
    [
      { type: :integer, name: :id, mode: :required },
      { type: :string, name: :value, mode: :required },
      { type: :integer, name: :question_id, mode: :required },
      { type: :integer, name: :user_id, mode: :required },
      { type: :string, name: :user_email, mode: :required },
      { type: :string, name: :question_name, mode: :required },
      { type: :string, name: :question_option1, mode: :required },
      { type: :string, name: :question_option2, mode: :required },
      { type: :integer, name: :survey_id, mode: :required },
      { type: :string, name: :survey_name, mode: :required }
    ]
  end

  def self.row(answer)
    {
      id: answer.id,
      value: answer.value,
      user_id: answer.user_id,
      user_email: answer.user.email,
      question_id: answer.question_id,
      question_name: answer.question.name,
      question_option1: answer.question.option_1,
      question_option2: answer.question.option_2,
      survey_id: answer.question.survey_id,
      survey_name: answer.question.survey.name
    }
  end
end

Job para crear un dataset

# app/jobs/create_bigquery_dataset_job.rb
class CreateBigqueryDatasetJob < ApplicationJob
  def perform
    client.create_dataset('bigquery_demo')
  end

  private

  def client
    @client ||= GoogleBigqueryClient.new
  end
end

Job para crear una tabla

# app/jobs/create_bigquery_answers_table_job.rb
class CreateBigqueryAnswersTableJob < ApplicationJob
  include AnswersData

  def perform
    client.create_table(
      'bigquery_demo', 'answers',
      AnswersData.attributes
    )
  end

  private

  def client
    @client ||= GoogleBigqueryClient.new
  end
end

Job para subir una answer a BigQuery

class UploadAnswerToBigqueryJob < ApplicationJob
  include AnswersData

  def perform(answer_id)
    answer = Answer.find(answer_id)

    client.insert_row('bigquery_demo', 'answers', AnswersData.row(answer))
  end

  private

  def client
    @client ||= GoogleBigQueryClient.new
  end
end

Observer

class AnswerObserver < PowerTypes::Observer
  after_create_commit :upload_to_google_bigquery
	...

  def upload_to_google_bigquery
    UploadAnswerToBigqueryJob.perform_later(object.id)
  end

	...
end

Recursos útiles

https://cloud.google.com/bigquery/docs/introduction

https://github.com/googleapis/google-cloud-ruby/tree/main/google-cloud-bigquery

**Sobre la **

No obstante, de manera que no sea tan complicado realizar el proceso de desnormalización.

data warehouse
desnormalización
BigQuery ofrece algunas soluciones para esto