Bỏ qua, đến nội dung

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ínhMô tả
typebelongsToArray
foreignKeyCột ARRAY/JSON trên source table
targetKeyPrimary key trên target table
targetTê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:

DatabaseStorage typeQuery hỗ trợ
PostgreSQLARRAY(DataTypes.INTEGER) hoặc ARRAY(DataTypes.STRING)@>, && (array operators)
MySQLJSONJSON_CONTAINS()
SQLiteTEXT (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 operations

So 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   │  │      │   └──────────────────┘  └──────┘
└──────┘  └─────────┘  └──────┘