2010-12-06 22 views
2

J'ai un fichier CSV que je veux lire avec Ruby et créer des objets Ruby à insérer dans une base de données MySQL avec Active Record. Quelle est la meilleure façon de faire cela? Je vois deux options claires: FasterCSV & le Ruby core CSV. Ce qui est mieux? Y a-t-il une meilleure option qui me manque?Meilleure façon de lire CSV dans Ruby. FasterCSV?

EDIT: Gareth dit d'utiliser FasterCSV, alors quelle est la meilleure façon de lire un fichier CSV en utilisant FasterCSV? En regardant la documentation, je vois des méthodes appelées parse, foreach, read, open ... On dit que foreach "est conçu comme l'interface principale pour lire les fichiers CSV." Donc, je suppose que je devrais utiliser celui-là?

+0

J'ai ajouté le tag MySQL pour rendre plus visible –

Répondre

4

Ruby 1.9 adopté FasterCSV as its core CSV processor, donc je dirais qu'il est certainement préférable d'opter pour FasterCSV, même si vous utilisez encore Ruby 1.8

+0

Cool, Merci! Comment l'utiliser pour lire un fichier CSV? – ma11hew28

+1

@MattDiPasquale Voir [les docs] (http://ruby-doc.org/ruby-1.9/classes/CSV.html). – Phrogz

+0

@Phrogz, merci! – ma11hew28

1

Si vous avez beaucoup d'enregistrements à vous importer pouvez utiliser MySQL's loader . Ça va être extrêmement rapide. LOAD DATA INFILE peut être utilisé pour lire des fichiers provenant de sources externes.

Par exemple, de nombreux programmes peuvent exporter des données au format CSV (valeurs séparées par des virgules), de sorte que les lignes ont des champs séparés par des virgules et placés entre guillemets doubles, avec une ligne initiale de noms de colonnes. Si les lignes dans un tel fichier sont terminées par paires retour chariot/saut de ligne, la commande ci-dessous illustre les options FIELDS et la ligne que vous utilisez pour charger le fichier:

LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name 
    FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
    LINES TERMINATED BY '\r\n' 
    IGNORE 1 LINES; 

Si la les valeurs d'entrée ne sont pas nécessairement entre guillemets, utilisez OPTIONALLY avant les mots-clés ENCLOSED BY.

utiliser pour tirer le tout dans une table temporaire, puis utilisez ActiveRecord pour exécuter des requêtes contre de supprimer des enregistrements que vous ne voulez pas, puis copiez de la table temporaire à votre production un, puis déposez ou tronquer la temp. Vous pouvez également utiliser ActiveRecord pour rechercher la table temporaire et copier les enregistrements en production, puis supprimer ou tronquer la température. Vous pourriez même être en mesure de faire une copie de table à table dans MySQL ou d'ajouter une table à une autre.

Il va être difficile de battre la vitesse du chargeur dédié et d'utiliser le mécanisme de requête de la base de données pour traiter les enregistrements en masse. L'étape consistant à transformer un enregistrement dans le fichier CSV en un objet, puis à utiliser l'ORM pour l'écrire dans la base de données ajoute beaucoup de frais supplémentaires, donc à moins que vous ayez des validations super difficiles nécessitant la logique de Ruby, vous serez plus rapide à la base de données.


EDIT: Voici un en-tête simple CSV à la colonne DB mappeur exemple:

require "csv" 

data = <<EOT 
header1, header2, header 3 
1, 2, 3 
2, 2, 3 
3, 2, 3 
EOT 

header_to_table_columns = { 
    'header1' => 'col1', 
    'header2' => 'col2', 
    'header 3' => 'col3' 
} 

arr_of_arrs = CSV.parse(data) 
headers = arr_of_arrs.shift.map{ |i| i.strip } 
db_cols = header_to_table_columns.values_at(*headers) 
arr_of_arrs.each do |ary| 
    # insert into the database using an ORM or by creating insert statements 
end