038. Array Field.

Written by Thach on

Một số trường hợp sử dụng array field trong Rails.
1. Migrate
# db/migrate/*_create_books.rb
class CreateBooks < ActiveRecord::Migration[6.0]
def change
create_table :books do |t|
t.string :title
t.string :tags, array: true, default: []
t.integer :ratings, array: true, default: []
t.timestamps
end
add_index :books, :tags, using: 'gin'
add_index :books, :ratings, using: 'gin'
end
end
# db/migrate/*_add_subjects_to_books.rb
class AddSubjectsToBooks < ActiveRecord::Migration
def change
add_column :books, :subjects, :string, array:true, default: []
end
end
2. Insert
Book.create(title: "Hacking Growth", tags: ["business", "startup"], ratings: [4, 5])
# <Book id: 1, title: "Hacking Growth", tags: ["business", "startup"], ratings: [4, 5], created_at: "2020-06-29 08:48:42", updated_at: "2020-06-29 08:48:42">
3. Show
book = Book.first
book.tags
# => ["business", "startup"]
book.tags[0]
# => "business"
4. Update
book.tags << 'management'
# => ["business", "startup", "management"]
book.save!
book.tags
# => ["business", "startup", "management"]
Nhưng mà đừng có làm thế này: Book.first.tags << 'finance'
, nó sẽ không được lưu vào database.
Book.first.tags << "finance"
# Book Load (0.3ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT $1 [["LIMIT", 1]]
# => ["business", "startup", "management", "finance"]
Book.first.save!
# Book Load (0.3ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT $1 [["LIMIT", 1]]
# => true
Book.first.tags
# Book Load (0.3ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT $1 [["LIMIT", 1]]
# => ["business", "startup", "management"]
5.Search
# Let say we want to search every single Book that have tags management:
Book.where("'management' = ANY (tags)")
# This is more secure
Book.where(":tags = ANY (tags)", tags: 'management')
# This is also valid
Book.where("tags @> ?", "{management}")
Book.where.not("tags @> ?", "{management}")
# Now, what if we want to search book that contain multiple tags, like management and startup
Book.where("tags @> ARRAY[?]::varchar[]", ["management", "startup"])
# OR contain any of tags
Book.where("tags && ARRAY[?]::varchar[]", ["management", "startup"])
# This is also valid
Book.where("tags && ?", "{management,startup}")
# If you use where.not, you basically search for all that do not contain the parameter given.
# Now what if we want to search all book that have rating more than 3:
Book.where("array_length(ratings, 1) >= 3")
# search matching, %gem% is manaGEMent
Book.where("array_to_string(tags, '||') LIKE :tags", tags: "%gem%")
Tham khảo hoàn toàn từ K Putra
Comments