Carga masiva de documentos en Couchbase
Este artículo es un ejemplo de cómo cargar datos como JSON en Couchbase. Para el propósito de este post, los datos extraídos de RDBMS como CSV serán convertidos a JSON. RDBMS DBAs y Admins familiarizados con Oracle, SQL server, MySQL, etc probablemente están buscando una manera de experimentar y probar con NoSQL. A menudo, el primer paso en el uso de NoSQL es convertir lo que tienes en JSON.
Couchbase soporta datos JSON y Binarios, pero para el propósito de este post estamos viendo el tipo de datos más rico, JSON.Esto es importante de entender porque al cargar documentos en Couchbase en un formato diferente a JSON, los datos serán cargados como binarios y pueden impactar la flexibilidad de la vista al tratar de construir vistas o índices. Dicho esto, vamos a cargar algunos documentos. Hay dos maneras de conseguirlo, pero para el propósito de este post asumo que cualquier documento que quieras cargar está ya en formato JSON y comprimido o sin comprimir. La siguiente sección describirá un posible camino para asegurar que estás cargando datos JSON.
Algunos socios de Couchbase ETL, como TalendTalend, que ofrece un conector para Couchbase si desea una interfaz gráfica de usuario, tal vez no quiere tratar con archivos CSV o desea reordenar sus datos antes de enviarlos a CSV o simplemente tiene la necesidad de ETL datos de varias fuentes antes de almacenar en Couchbase Server. Talend puede mapear y almacenar documentos directamente como archivos JSON antes de cargarlos en Couchbase, si se desea .
Esta guía asume que tienes cierta familiaridad con Linux o Mac, gestores de paquetes y Ruby.
Para obtener más información sobre la configuración del SDK, visite www.couchbase.com/developers/
Los pasos utilizados para preparar y cargar los datos son los siguientes:
- Preparar los datos: Mira un par de herramientas de ejemplo para convertir el CSV a JSON.
- Cargar los datos: Examinar algunos métodos para cargar los datos en couchbase a través de scripts Ruby.
Requisitos previos para Linux y Mac: Requiere un entorno de construcción funcional.
- Libcouchbase: Dado que este script utiliza Ruby debes tener instalado libcouchbase antes de instalar la gema couchbase
- rubygem: asegúrese de que dispone de rubygems para instalar la envoltura ruby couchbase
- Las gemas que he utilizado son
- ruby-progressbar
- couchbase
- yaji
- optparse
- Las gemas que he utilizado son
- Yajl parser: también debe instalarse como requisito previo a YAJI.
- Instalar Couchbase Gem: gem install couchbase
Si la configuración se ha realizado correctamente, los scripts ruby que he proporcionado deberían ejecutarse. Puede que quieras pasar -h al streamloader y asegurarte de que recibes el mensaje de sintaxis. Por último, no te olvides de instalar los GEMs enumerados también, Yaji, optparse, couchbase, y ruby-progressbar. Los enlaces se proporcionan en la parte inferior de este post.
Preparar los datos
Método de preparación de datos 1: sencillo, rápido y coherente: csvtojson Script NodeJS
- Se puede encontrar a través de Google para y hay otros también.
- Se instala mediante NPM ala
npm install -g csvtojson
Aquí tienes un ejemplo de conversión como referencia:
|
1 2 3 4 5 6 7 |
Austins-MBP:complaintstemp austin$ npm info csvtojson { name: 'csvtojson', description: 'A tool concentrating on converting csv data to JSON with customised parser supporting', 'dist-tags': { latest: '0.3.21' }, Austins-MBP:complaintstemp austin$ which csvtojson /usr/local/bin/csvtojson Austins-MBP:complaintstemp austin$ csvtojson data.gov_Consumer_Complaints.csv |
Método 2 de preparación de datos: Escribir un script Ruby: csv2json.rb
El tiempo para completar el proceso variará porque Ruby es monohilo.
Una nota adicional para este script es que estoy usando la función YAJL en lugar del módulo JSON por defecto, que no maneja la transmisión de datos a Couchbase.
El script de abajo muestra el único cambio necesario. Esto mejorará el uso de memoria durante la conversión. Si no ha instalado YAJL antes de que usted puede simplemente hacer esto: 'gem install yajl-ruby'
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/usr/bin/env ruby require 'rubygems' require 'csv' require 'pathname' #require 'JSON' require 'yajl/json_gem' Dir["./**/*.csv"].each do |csv_file_path| puts csv_file_path file_name = Pathname.new(csv_file_path).basename(".csv").to_s File.open("#{file_name}.json",'w') do |json_file| jsonData = CSV.read(csv_file_path, :headers => true, :header_converters => :symbol).map{|csv_row| csv_row.to_hash} json_file.write(JSON.pretty_generate(jsonData)); end end |
Pasos posteriores a la conversión
Una vez finalizada la conversión, es hora de comprimir el archivo con ZIP:
|
1 2 3 4 5 |
Austins-MBP:complaintstemp austin$ ls Consumer_Complaints.csv Consumer_Complaints.json csv2json.rb Austins-MBP:complaintstemp austin$ zip Consumer_Complaints.zip Consumer_Complaints.json adding: Consumer_Complaints.json (deflated 95%) |
Coloca los archivos zip en un directorio. Yo he utilizado ~/Downloads/json_files/ en mi directorio personal.
|
1 |
Austins-MBP:complaintstemp austin$ cp Consumer_Complaints.zip ~/Downloads/json_files/ |
Una vez que los datos han sido preparados, estás listo para empezar a cargarlos. Los siguientes ejemplos se refieren a un par de maneras comunes de obtener sus datos en Couchbase a granel.
La instalación de Couchbase viene con una herramienta integrada llamada cbcdocloader. Toma archivos de documentos individuales, de hasta 20 MB de tamaño, comprimidos o dentro de un directorio y los carga. En el momento de escribir este artículo cbcdocloader requiere múltiples archivos formateados en JSON contenidos en un directorio. En segundo lugar, hablaré de una herramienta que escribí en Ruby y que emplea la herramienta de Couchbase, Sergey Asavayev. YAJI Gema Ruby. El código al que se hace referencia es de uso libre y puede reescribirse en cualquier lenguaje con el que te sientas cómodo.
Método 1 de carga de documentos cbcdocloader
Utilizar un conjunto de archivos individuales dentro de un directorio es un caso de uso común, pero depende de que la estructura de los archivos y directorios que se van a importar refleje los documentos deseados tal y como aparecerán una vez cargados. Para ayudar a preservar esa estructura, recomendamos empaquetar los archivos y directorios que se van a cargar en un archivo .zip.
Los nombres de las claves de identificación de los documentos se basarán en los archivos de documentos proporcionados.
Nota: tste método no es ideal para grandes ficheros de documentos consolidados. Para grandes ficheros monolíticos ejemplificaré cómo se cargan en el Método 2, más abajo.
A continuación, cargue el archivo o archivos mediante el siguiente comando:
|
1 2 3 |
cbdocloader -u Administrator -p s3kre7Pa55 -b MyBucketToLoad -n 127.0.0.1:8091 -s 1000 ~/json_files/beer-sample.zip |
Nota:
El '-s 1000' es el tamaño de memoria para el cubo. Tendrás que ajustar este valor para tu cubo.
Tampoco es necesario que el cubo exista como cbcdocloader lo creará, pero sea consciente de la utilización de sus recursos antes de configurar el indicador '-s' para asegurarse de que tiene RAM disponible.
Si todo ha ido bien, verás un mensaje indicando si se han cargado documentos, cuántos bytes, etc.
|
1 2 3 4 5 |
bucket: 2014-10-02-ny-json.zip, msgs transferred... : total | last | per sec byte : 242446488 | 242446488 | 3115728.2 |
He aquí un breve script para cargar un montón de archivos .zip en un directorio determinado:
|
1 2 3 4 5 6 7 8 |
#!/bin/bash JSON_Dir=~/json_files/ for ZipFile in $JSON_Dir/*.zip ; do /Applications/Couchbase Server.app/Contents/Resources/couchbase-core/bin/cbdocloader -u Administrator -p s3kre7Pa55 -b MyBucketToLoad -n 127.0.0.1:8091 -s 1000 $ZipFile done |
Método de carga de documentos 2: streamloadjson
El otro método consiste en cargar todos los documentos, separados por comas, desde un único archivo monolítico.
Para llevar a cabo este método he preparado un pequeño pero efectivo script que utiliza el parser YAJI JSON stream y lo he llamado streamjsonload.
Las opciones de este programa son:
|
1 2 3 4 5 6 7 8 |
~$ ruby streamloadjson.rb -h ruby json loader -f, --jsonfile jsonfile JSON formatted filename -b, --bucketname BUCKETNAME bucket name -n, --hostname hostname hostname/ip address -r, --root JSONroot JSON root to parse -d, --docid SearchKey JSON Key ID -h, --help This menu |
Para cargar documentos con un archivo JSON de prueba como padres.json.txt de abajo, se puede llamar así:
|
1 |
ruby streamloadjson.rb -b TestBucket -f fathers.json -n localhost -d id -r /fathers/ |
El script debe proporcionar una salida como la siguiente:
|
1 2 3 4 |
Reading from fathers.json JSON path processed is /fathers/ Couchbase node is localhost 29999 Time: 00:00:07 |>>---=---=---=---=---| Doc Loading |
Una gran ventaja de utilizar el analizador YAJI es que requiere un consumo de memoria muy bajo. Esto significa que potencialmente podrías paginar los datos de entrada y dividirlos en múltiples flujos para cargarlos en couchbase. Generará procesos discretos ya que Ruby es de un solo hilo, pero también se podría utilizar otro lenguaje para multihilos. Un ejemplo de esto está en el repositorio Github de Couchbase Labs.
Un par de cosas a tener en cuenta, Esta herramienta sólo carga archivos de documentos monolíticos, intentará crear un ID automáticamente si no se proporciona uno con '-d' y requerirá algún ajuste fino de la "raíz" con -r si no se cargan documentos.
Código más reciente para el cargador está disponible en mi repositorio githubpero también lo he puesto en línea más abajo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
#!/usr/bin/env ruby #An example JSON file for testing is at: # https://github.com/ysharplanguage/FastJsonParser/raw/master/JsonTest/TestData/fathers.json.txt require 'ruby-progressbar' require 'rubygems' require 'couchbase' require 'yaji' require 'optparse' options = {} optparse = OptionParser.new do |opts| opts.banner = 'ruby json loader' opts.on('-f', '--jsonfile jsonfile', 'JSON formatted filename') do |jsonfile| options[:jsonfile] = jsonfile end opts.on('-b', '--bucketname BUCKETNAME', 'bucket name') do |bucketname| options[:bucketname] = bucketname end opts.on('-n', '--hostname hostname', 'hostname/ip address') do |hostname| options[:hostname] = hostname end opts.on('-r', '--root JSONroot', 'JSON root to parse') do |root| options[:root] = root end opts.on('-d', '--docid SearchKey', 'JSON Key ID') do |docid| options[:docid] = docid end opts.on('-h', '--help', 'This menu') { puts opts; exit} end optparse.parse! json_file = options[:jsonfile] bucket = options[:bucketname] host = options[:hostname] root = options[:root] docid = options[:docid] #set some defaults if not passed unless host host=localhost end unless root root="/" end puts "Reading from #{json_file}" puts "JSON path processed is #{root}" puts "Couchbase node is #{host}" # Connect to couchbase host and bucket provided on the command line client = Couchbase.connect(:bucket => bucket, :host => host) #Create the progressbar progressbar=ProgressBar.create(:title => "Doc Loading", :starting_at => 0, :total => nil, :throttle_rate => 0.01, :format => '%a |%b>>%i| %p%% %t', :length => 50) parser = YAJI::Parser.new(File.open(json_file)) parser.each(root.to_s).with_index do |doc,i| unless docid hashinfo=doc.hash.abs prikey="Doc_#{i}:#{hashinfo}" end prikey="#{docid}:#{doc["#{docid}"]}" client.set("#{prikey}", doc) print("rProcessed #{i} Documents") progressbar.increment end progressbar.finished? puts |
Acabar el trabajo
Una vez cargados los datos, inicia sesión en la consola de Couchbase y empieza a trabajar con vistas de desarrollo para consultas e indexación.
Si utiliza Couchbase Server 4.0 con N1QL ¡querrás crear un índice primario para poder explorar la interfaz tipo SQL de Couchbase inmediatamente y empezar a aprovechar el poder de consulta de N1QL a través de nuestros SDKs!
Muchas gracias a la gran gente de la comunidad Open Source por proporcionar la gema YAJL y a Sergey Avseyev por el parser YAJI. Sergey es un recurso de Couchbase muy bien informado responsable del trabajo del SDK de Ruby y también me gustaría animar a cualquiera de ustedes a probar nuestro SDK de JRuby y proporcionar retroalimentación.
Enlaces:
CB Ejemplos Github - https://github.com/agonyou/cb-examples/
YAJI Stream Parser - https://github.com/avsej/yaji
Gema YAJL JSON - https://github.com/brianmario/yajl-ruby
csv2json Gem - https://rubygems.org/gems/csv2json/
Couchbase Server 4 con N1QL - https://www.couchbase.com/nosql-databases/downloads
Si ejecuto \'./cbdocloader -u tito -p foobar -b test -n 192.168.1.4:8091 -s 1000 /Users/tito/Desktop/muestra.zip \' y el archivo de muestra contiene una matriz JSON con sólo dos documentos, todo el contenido del archivo se importa como un documento. En otras palabras, cbdocloader no parece darse cuenta de que el documento es un array de objetos JSON. Además, el editor muestra \ 'Advertencia: JSON should not be an array\'. ¿Cómo se supone que funciona cbdocloader? Gracias.
Por cierto, si utilizo el JSON de ejemplo que se encuentra en \'https://www.rubydoc.info/gems/c..., obtengo el mismo problema. En ambos casos, el contenido del archivo es JSON válido. Parece que cbdocloader no coopera :-/
Bien montado, también podría utilizar https://sqlify.io/convert/csv/to/json para convertir a JSON y luego cargar los documentos como normal en lugar de rodar su propio script.