Giao diện
Tham chiếu kỹ thuật
belongsToArray trên SequelizeCollectionManager
Plugin đăng ký relation type belongsToArray vào SequelizeCollectionManager, mở rộng hệ thống quan hệ ORM:
| Thuộc tính | Mô tả |
|---|---|
| type | belongsToArray |
| foreignKey | Cột ARRAY/JSON trên source table |
| targetKey | Primary key trên target table |
| target | Tên target collection |
Khi hệ thống sync model, cột foreignKey được tạo với type phù hợp theo database.
ARRAY / JSON / JSONB Storage
Cách lưu trữ phụ thuộc database engine:
| Database | Storage type | Query hỗ trợ |
|---|---|---|
| PostgreSQL | ARRAY(DataTypes.INTEGER) hoặc ARRAY(DataTypes.STRING) | @>, && (array operators) |
| MySQL | JSON | JSON_CONTAINS() |
| SQLite | TEXT (JSON serialized) | Hạn chế — parse trong application |
PostgreSQL ARRAY — Hiệu năng tốt nhất
sql
-- Tìm posts có tag 3
SELECT * FROM posts WHERE tag_ids @> ARRAY[3];
-- Tìm posts có bất kỳ tag 1, 3, 5
SELECT * FROM posts WHERE tag_ids && ARRAY[1, 3, 5];MySQL JSON
sql
SELECT * FROM posts WHERE JSON_CONTAINS(tag_ids, '3');Hooks — afterCreate / beforeDestroy
afterCreate — FK wiring
Bản ghi mới được INSERT
→ afterCreate hook trigger
→ Lấy giá trị cột array (ví dụ: [1, 3, 5])
→ Verify tất cả target keys tồn tại trong target table
→ Nếu key không tồn tại → warning log (không block)Hook đảm bảo tính toàn vẹn tham chiếu ở tầng application. Không tạo DB-level foreign key constraint vì cột array không hỗ trợ.
beforeDestroy — Cleanup
Bản ghi chuẩn bị DELETE
→ beforeDestroy hook trigger
→ Kiểm tra cascade rules
→ Cleanup references nếu cần (xóa target key khỏi array ở bản ghi khác)Nested Create / Update
Plugin hỗ trợ tạo/cập nhật target record lồng nhau:
Nested create
Input: { tags: [{ id: 3 }, { name: "New Tag" }] }
→ Phân loại:
- { id: 3 } → reference existing (thêm 3 vào array)
- { name: "New Tag" } → create new → INSERT vào target → lấy id = 7
→ Cập nhật array: [3, 7]Nested update
Input: { tags: [{ id: 3, name: "Updated Tag" }] }
→ { id: 3 } tồn tại → UPDATE record 3 trong target table
→ Array giữ nguyên: [3]Replace vs Append
Khi update bản ghi, giá trị array được thay thế hoàn toàn (replace), không phải append:
Trước: tagIds = [1, 3, 5]
Update: tags = [{ id: 2 }, { id: 4 }]
Sau: tagIds = [2, 4] ← replace toàn bộResolver — Đọc dữ liệu
Khi đọc bản ghi có belongsToArray field:
Query: repository.find({ appends: ['tags'] })
→ Lấy bản ghi với cột tagIds = [1, 3, 5]
→ Resolve: SELECT * FROM tags WHERE id IN (1, 3, 5)
→ Map kết quả vào field 'tags'
→ Trả về bản ghi với tags: [{ id: 1, name: "..." }, ...]Đăng ký vào ORM
Plugin install()
→ SequelizeCollectionManager.registerRelationType('belongsToArray', BelongsToArrayRelation)
→ Đăng ký hooks afterCreate, beforeDestroy
→ Đăng ký resolver cho nested operationsSo sánh kiến trúc
M2M truyền thống: M2M Array:
┌──────┐ ┌─────────┐ ┌──────┐ ┌──────────────────┐ ┌──────┐
│ Post │→ │post_tags│ →│ Tag │ │ Post │→ │ Tag │
│ │ │post_id │ │ │ │ tagIds: [1,3,5] │ │ │
│ │ │tag_id │ │ │ └──────────────────┘ └──────┘
└──────┘ └─────────┘ └──────┘