Sử dụng JSON Columns trong Eloquent: Cách tiếp cận lai SQL/NoSQL

· 3 min read

Thiết kế cơ sở dữ liệu quan hệ truyền thống (Normalization) nói: "Nếu bạn có danh sách các item, hãy tạo một bảng riêng".

Nhưng đôi khi bạn chỉ muốn lưu trữ "Settings", "Metadata", hoặc các thuộc tính động mà không cần tạo 10 bảng mới.

Đây là lúc kiểu cột JSON xuất hiện.

Migration

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->json('attributes'); // { "color": "red", "size": "XL" }
    $table->timestamps();
});

Eloquent Casting

Cho Eloquent biết cần tự động chuyển đổi chuỗi JSON thành Array (hoặc Object).

protected $casts = [
    'attributes' => 'array',
];

Bây giờ bạn có thể sử dụng nó như một PHP array bình thường:

$product->attributes['color'] = 'blue';
$product->save();

Truy vấn JSON

Laravel làm điều này cực kỳ dễ dàng sử dụng cú pháp ->.

// Tìm products có color là red
$products = Product::where('attributes->color', 'red')->get();

// Tìm size large
$products = Product::where('attributes->size', 'XL')->get();

// Keys lồng nhau
$products = User::where('meta->settings->notifications->email', true)->get();

Cập nhật JSON một phần

Bạn có thể cập nhật một key đơn lẻ mà không ghi đè toàn bộ JSON blob.

$product->update(['attributes->color' => 'green']);

Cảnh báo về hiệu năng

Truy vấn JSON chậm hơn các cột chuẩn. Nếu bạn truy vấn attributes->color trên mỗi lần tải trang, hãy tách nó ra thành một cột thực.

Tuy nhiên, bạn có thể đánh index cho JSON keys sử dụng "Generated Columns" trong MySQL 5.7+ / MariaDB.

$table->string('color')->virtualAs('attributes->>"$.color"')->index();

Điều này tạo một virtual column color cho phép đánh index hiệu suất cao trong khi vẫn giữ dữ liệu trong cấu trúc JSON.

Bình luận