07/09/2018, 17:44

[Bulk insert] Đôi chút về gem 'activerecord-import' và cách sử dụng.

Khi phát triển phần mềm, việc ứng dụng sẽ có mốt số chức năng cần insert số lượng lớn bản ghi là điều dễ dàng gặp, ví dụ như thêm dữ liệu từ file excel, xml... hay khi ứng dụng được nâng cấp, đổi mã nguồn thì thường cần thiết phải convert một số lượng lớn dữ liệu từ hệ thống cũ. Nếu xây dựng hệ ...

Khi phát triển phần mềm, việc ứng dụng sẽ có mốt số chức năng cần insert số lượng lớn bản ghi là điều dễ dàng gặp, ví dụ như thêm dữ liệu từ file excel, xml... hay khi ứng dụng được nâng cấp, đổi mã nguồn thì thường cần thiết phải convert một số lượng lớn dữ liệu từ hệ thống cũ.

Nếu xây dựng hệ thống với Rails framework và để xử lý vấn đề trên thì sẽ gặp đôi chút khó khăn bởi native rails không hỗ trợ insert multi record với ActiveRecord(ORM). Ví dụ để insert 100 hay 1000 bản ghi chúng ta sẽ phải kết nối 100 hay 1000 lần tới database, tưởng tượng ứng dụng sẽ phải đóng mở kết nối và thao tác với DB 100 - 1000 lần và càng tăng lên gấp nhiều lần nếu số lương record tăng lên. Xem hình bên dưới sẽ thấy được plan và thời gian cho mỗi lần commit với database.

Để giải quyết vấn đề trên ta sẽ có vài cách như sử dụng thủ tục(procedure) hoặc viết scope, nhưng viết thủ tục hay scope thì đều phải viết riêng cho từng đối tượng và quan tâm đến security sẽ gây tốn effort cho chúng ta. Một giải pháp nhanh hơn là sử dụng Gem, mình đã thử qua vài gem thì thấy có gem activerecord-import là dễ sử dụng và đơn giản hơn cả.

Cài đặt

Thêm gem "activerecord-import" vào gemfile sau đó chạy bundle install trên màn hình terminal.

Cách sử dụng

Có 5 cách viết để sử dụng với activerecord-import

  1. import sử dụng mảng tên cột và mảng giá trị (Arrays column and values)
columns = [ :title, :author ]
values = [ ['Book1', 'FooManChu'], ['Book2', 'Bob Jones'] ]

# Import không sử dụng validations
Book.import columns, values, :validate => false

# Import có validations với Model
Book.import columns, values, :validate => true

# nếu không có thiết lập gì thì mặc định validate sẽ là true
Book.import columns, values
  1. import sử dụng mảng hashes (Arrays Hashes)
values = [{ title: 'Book1', author: 'FooManChu' }, { title: 'Book2', author: 'Bob Jones'}]

# Import không sử dụng validations
Book.import values, validate: false

# Import có validations với Model
Book.import values, validate: true

# nếu không có thiết lập gì thì mặc định validate sẽ là true
Book.import values
  1. import sử dụng mảng hashes và chỉ định rõ tên cột cần lưu vào database (Arrays Hashes and Explicit Column Names)
books = [ 
  {title: "Book 1", author: "FooManChu"},
  {title: "Book 2", author: "Bob Jones"}
]
columns = [ :title ]

# Import không sử dụng validations
Book.import columns, books, validate: false

# Import có validations
Book.import columns, books, validate: true

# nếu không có thiết lập gì thì mặc định validate sẽ là true
Book.import columns, books

# Kết quả trong bảng books khi thực hiện import xong.
# title  | author
#--------|--------
# Book 1 | NULL   
# Book 2 | NULL   
  1. import sử dụng ActiveRecord Models
books = [ 
  Book.new(:title => "Book 1", :author => "FooManChu"),
  Book.new(:title => "Book 2", :author => "Bob Jones")
]

# Import không sử dụng validations
Book.import books, :validate => false

# Import có validations với Model
Book.import books, :validate => true

# nếu không có thiết lập gì thì mặc định validate sẽ là true
Book.import books
  1. import sử dụng ActiveRecord Models và chỉ định rõ tên cột cần lưu vào database (ActiveRecord Models and Explicit Column Names)
books = [ 
  Book.new(:title => "Book 1", :author => "FooManChu"),
  Book.new(:title => "Book 2", :author => "Bob Jones")
]
columns = [ :title ]

# Import không sử dụng validations
Book.import columns, books, :validate => false

# Import có sử dụng validations
Book.import columns, books, :validate => true

# nếu không có thiết lập gì thì mặc định validate sẽ là true
Book.import columns, books

# kết quả trong bảng books sau khi thực hiện import xong.
# title  | author
#--------|--------
# Book 1 | NULL   
# Book 2 | NULL   
0