MongoDB và Rails

MongoDB và Rails

1 NoSQL

NoSQL ra đời năm 1998 bởi Carlo Strozzi. Sự xuất hiện của NoSQL với nhiều đặc điểm mới lạ như không lưu trữ dữ liệu dưới dạng các bảng và các cột như sql, dữ liệu không quan hệ - không có sự ràng buộc nào cho việc nhất quán dữ liệu, điều này làm cho việc đọc ghi dữ liệu trong NoSQL rất nhanh phù hợp với các dự án có dữ liệu lớn, chịu tải cao và ứng dụng yêu cầu thời gian thực.

Các dạng NoSQL cơ bản

Key – value data store

Dữ liệu lưu dưới dạng cặp key – value. Giá trị được truy xuất thông qua key.
Ví dụ : Redis, Dynomite, Project Voldemort.
Thường cho: Lưu trữ trong bộ đệm
Ưu điểm: Tìm kiếm rất nhanh
Nhược điểm: Lưu dữ liệu không theo khuôn dạng (schema) nhất định

Column-based – Tabular

Cơ sở dữ liệu tổ chức dưới dạng các bảng. Gần giống với mô hình RDBMS. Tuy nhiên, chúng lưu dữ liệu bởi các cột chứ không phải bằng các dòng. Nó khá thích hợp với để hiển thị bằng các phần mềm quản lý kho dữ liệu
Ví dụ : Apache Hbase, Apache Cassandra, Hypertable
Thường cho: các hệ phân tán file
Ưu điểm: Tìm kiếm nhanh, phân tán dữ liệu tốt
Nhược điểm: Hỗ trợ được với rất ít phần mềm

Document-based

Dữ liệu (bán cấu trúc hay semi-structured) được lưu trữ và tổ chức dưới dạng một tập hợp các document. Các document này linh hoạt, mỗi document có một tập nhiều trường.
Ví dụ : Apache CouchDB và MongoDB
Thường cho: Web applications
Ưu điểm: Dùng khi dữ liệu nguồn không được mô tả đầy đủ
Nhược điểm: Không có cú pháp chuẩn cho câu truy vấn dữ liệu

Graph-based data-stores

Những CSDL này áp dụng lý thuyết đồ thị trong khoa học máy tính để lưu trữ và truy xuất dữ liệu. Chúng tập trung vào tính rời rạc giữa các phần dữ liệu. Các phần tử đơn vị dữ liệu được biểu thị như một nút và liên kết với các thành phần khác bằng các cạnh.
Ví dụ : Neo4j, InfiniteGraph, DEX
Thường cho: Social networking
Ưu điểm: Ứng dụng các thuật toán trên đồ thị như Đường đi ngắn nhất, liên thông,…
Nhược điểm: Phải duyệt nội bộ đồ thị, để trả lời lại các truy vấn. Không dễ để phân tán

2 MongoDB

MongoDB là một hệ quản trị cơ sở dữ liệu NoSQL phổ biến thuộc loại Document-based và được sử dụng rộng rãi. MongoDB lưu trữ dữ liệu dựa trên cấu trúc JSON với mô hình động gọi là BSON. Dưới đây là một vài so sánh giữa RDBMS (mô hình dữ liệu quan hệ) và MongoDB

RDBMS MongoDB
Tables Collections
Columns, Rows Keys, values
Indexes Indexes
Views, Functions, Procedures, Contraints, Triggers Không có
Primary Keys ObjectId (mặc định là _id)
Foreign Keys Không có

MongoDB server sẽ chứa nhiều database. Mỗi database lại chứa một số colection. Mỗi colection là một tập các documnents, về mặt logic thì chúng gần tương tự như các table trong CSDL quan hệ. Tuy nhiên, điểm hay ở đây là ta không cần phải định nghĩa trước cấu trúc của colection … Một document là một đơn vị dữ liệu lưu trữ theo kiểu key-value. Key là một chuỗi ký tự, dùng để truy xuất giá trị dạng : string, integer, double, … Dưới đây là một ví dụ về MongoDB document

{
_id : ObjectId("4db31fa0ba3aba54146d851a"),
username : "test",
email : "[email protected]",
age : 26,
is_admin : true,
created : "Sun Apr 24 2011 01:52:58 GMT+0700 (BDST)"
}

3 MongoDB và Rails

Cài đặt Mongodb

Đầu tiên nếu bạn tạo một ứng dụng mới với rails new <tên app> thì bạn thêm --skip-active-record để bỏ qua ActiveRecord dependencies.

rails new my_app --skip-active-record

Nếu bạn đã có ứng dụng rồi và muốn thay đổi từ sang MongoDB thì bạn cần mở file config/application.rb và thay thế:

require 'rails/all'

Với Rails 3 thì bạn thay thế như sau:

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"

Với Rails 4 thì thay thế như sau:

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_model/railtie"
require "action_view/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"

Sau đó bạn thêm 2 gem sau vào Gemfile và chạy bundle install để cài đặt chúng trên máy của bạn:

gem 'mongo_mapper'
gem 'bson_ext'

Tiếp sau đó bạn cần cấu hình thông tin của MongoDB server. trong file config/mongo.yml. Để tạo ra file này bạn có thể chạy lệnh sau:

bundle exec rails generate mongo_mapper:config

Nếu bạn đã quen với việc tạo các Model trong Rails với lệnh rails generate model ... bạn cần config lại generators trong config/application.rb như sau:

config.generators do |g|
  g.orm :mongo_mapper
end

Ví dụ để tạo một model user với các thuộc tính như name:string ta chạy lệnh sau:

rails g model user name:string
invoke  mongo_mapper
create    app/models/user.rb
invoke    test_unit
create      test/models/user_test.rb
create      test/fixtures/users.yml

Sau khi chạy lệnh này bạn sẽ có thêm file app/models/user.rb và 2 file dùng để kiểm thử là test/models/user_test.rb và test/fixtures/users.yml. Tuy nhiên nếu bạn không cần kiểm thử thì chỉ cần file app/models/user.rb và bạn có thể tạo thủ công cũng không sao cả. Có một điểm chú ý ở đây là với ActiveRecord thì ta sẽ có thêm một file migrate để thay đổi cấu trúc dữ liệu (thêm bảng users), nhưng với MongoDB thì điều này không cần thiết bởi dữ liệu lưu trữ trong MongoDB là dữ liệu động.

Ngay bây giờ bạn có thể sử dụng và thao tác với model User này thông qua rails c

Loading development environment (Rails 4.1.1)
irb(main):001:0> user = User.new(name: 'Mongo')
=> #<User _id: BSON::ObjectId('539645eb43ebd927b2000001'), name: "Mongo">
irb(main):002:0> user.valid?
=> true
irb(main):003:0> user.save
=> true
irb(main):004:0> User.all.count
=> 1

Nếu bạn muốn deploy lên một webserver như heroku bạn có thể sử dụng cơ sở dữ liệu miễn phí MongoDB do mongolab cung cấp.

Như vậy việc cài đặt MongoDB cho Rails đã hoàn thành. Bạn có thể thấy, với Ruby on Rails mọi thứ đều trở nên đơn giản. Phần tiếp theo tôi xin nói về truy vấn trong MongoDB có khá nhiều điểm khác biệt so với ActiveRecord.

Truy vấn trong MongoDB

where

Tìm kiếm các bản ghi thỏa mãn điều kiện where.

Model.where(:column1 => value1)
Model.where(:column1 => value1, :column2 => value2, ...)

Chú ý: Truy vấn where trong MongoDB có một vài điểm khác biệt so với trong truy vấn sql thông thường. Khi so sánh lớn hơn hoặc nhỏ hơn với ActiveRecord (sử dụng cơ sở dữ liệu quan hệ) ta có thể dùng như sau Model.where('id > 100') hoặc Model.where('id < 100') còn với MongoDB ta cần thêm một số method sau cho symbol: gt (lớn hơn), lt (nhỏ hơn), gte (lớn hơn hoặc bằng), lte (nhỏ hơn hoặc bằng) ví dụ

Model.where(:view.gt => 100) hoặc Model.where(:view.lt => 100)...

find

Tìm kiếm 1 hoặc nhiều bản ghi theo id của chúng. Nếu không tìm thấy bất cứ id nào thì sẽ sinh ra lỗi

Model.find('4baa56f1230048567300485c')
Model.find(
  "4baa56f1230048567300485c",
  "4baa56f1230048567300485d"
)
Model.where(name: 'test').find('4baa56f1230048567300485c')

find_by

Tìm duy nhất một bản ghi thỏa mãn điều kiện nào đó

Model.find_by(:column => value)

fields

Dùng để lấy một số trường dữ liệu trong một model cho mỗi bản ghi kết quả (không phải tất cả). Truy vấn này tương đương với pluck trong ActiveRecord

Model.where(:column.gt > 100).fields(:column1, :column2, ...)

count

Đếm số lượng kết quả thỏa mãn điều kiện

Model.count
Model.where(:column.gt > 100).count

limit

Lấy ra số lượng bản ghi theo mong muốn

Model.where(:column.gt >100).limit(10)

skip, offset

Lấy ra bản ghi bắt đầu từ vị trí nào đó

Model.where(:column.gt > 100).limit(10).offset(2)

sort, order

Sắp xếp kết quả tăng dần hoặc giảm dần

Model.sort(:column => :asc)
Model.sort(:column => :desc)
Model.sort(:column1 => :asc, :column2 => :desc)

create

Tạo tài liệu (trong ActiveRecord gọi là bản ghi) với params truyền vào là một Hash tương tự khi sử dụng ActiveRecord.

Model.create(:column1 => value1, column2 => value2, ...)

destroy

Xóa 1 hoặc nhiều tài liệu theo id của chúng hoặc xóa một đối tượng tài liệu.

Model.destroy('50a210d2f7aa6006d2000001')
Model.destroy('50a210d2f7aa6006d2000001', '50a21153f7aa6006d2000002', ...)
m = Model.find_by(:column => value)
m.destroy if m.present?

destroy_all

Xóa tất cả các bản ghi thỏa mãn điều kiện

Model.destroy_all
Model.where(:column.gt => 100).destroy_all

delete

Tương tự destroy và không gọi các callbacks khi xóa bản ghi

delete_all

Tương tự destroy_all và không gọi callbacks khi xóa bản ghi

Trên đây là một số truy vấn cơ bản trong MongoDB sử dụng gem mongo_mapper. Một điểm chú ý là trong MongoDB không hỗ trợ truy vấn joins bạn nên thận trọng với những dữ liệu cần đến truy vấn joins.

4 Kết luận

MongoDB là một hệ quản trị cơ sở dữ liệu NoSQL. Với nhiều đặc điểm mới về tư tưởng cũng như nguyên lý hoạt động so với hệ quản trị cơ sở dữ liệu quan hệ (RDBMS), hơn nữa MongoDB có tốc độ đọc ghi nhanh, phù hợp với các dự án yêu cầu lưu trữ lượng lớn dữ liệu. Vì vậy số lượng ứng dụng sử dụng NoSQL và đặc biệt MongoDB phát triển nhanh chóng. Qua bài viết này hi vọng giúp bạn phần nào hiểu và sử dụng được MongoDB database cho ứng dụng Ruby on RAILS. Cảm ơn bạn đã theo dõi bài viết.


All Rights Reserved