2016-12-05 38 views
13

Tôi đang ở ngã tư quyết định xem thẻ có nên là tài nguyên của riêng họ hay thuộc tính lồng nhau của ghi chú hay không. Câu hỏi này chạm một chút vào thiết kế RESTful và lưu trữ cơ sở dữ liệu.Thẻ có nên là tài nguyên của chính nó hay thuộc tính lồng nhau không?

Bối cảnh: Tôi có tài nguyên ghi chú. Người dùng có thể có nhiều ghi chú. Mỗi ghi chú có thể có nhiều thẻ.

Mục tiêu chức năng: tôi cần phải tạo ra các tuyến đường để làm như sau:
1) Fetch tất cả các thẻ sử dụng. Một cái gì đó như: GET /users/:id/tags
2) Xóa (các) thẻ được liên kết với ghi chú.
3) Thêm thẻ vào một ghi chú cụ thể.

Mục tiêu dữ liệu/hiệu suất
1) Tìm nạp thẻ người dùng phải nhanh. Điều này là dành cho mục đích "tự động đề xuất"/"tự động hoàn tất".
2) Ngăn chặn các bản sao (càng nhiều càng tốt). Tôi muốn thẻ được sử dụng lại càng nhiều càng tốt cho mục đích có thể truy vấn dữ liệu theo thẻ. Ví dụ: tôi muốn giảm thiểu các tình huống mà người dùng nhập một thẻ như "siêu anh hùng" khi thẻ "siêu anh hùng" đã tồn tại.

Điều đó đang được nói, cách tôi nhìn thấy nó, có hai phương pháp lưu trữ thẻ trên một tài nguyên lưu ý:

1) thẻ là tài sản lồng nhau. Ví dụ:

type: 'notes', 
attributes: { 
    id: '123456789', 
    body: '...', 
    tags: ['batman', 'superhero'] 
} 

2) thẻ làm tài nguyên của riêng chúng. Ví dụ:

type: 'notes', 
data: { 
    id: '123456789', 
    body: '...', 
    tags: [1,2,3] // <= Tag IDs instead of strings 
} 

Một trong hai cách tiếp cận trên có thể hoạt động nhưng tôi đang tìm giải pháp cho phép khả năng mở rộng và nhất quán dữ liệu (tưởng tượng triệu ghi chú và mười triệu thẻ). Tại thời điểm này, tôi đang nghiêng về tùy chọn # 1 vì nó dễ dàng hơn để đối phó với mã khôn ngoan nhưng có thể không nhất thiết phải là tùy chọn đúng.

Tôi rất thích nghe một số suy nghĩ về các cách tiếp cận khác nhau đặc biệt là vì tôi không thể tìm thấy một câu hỏi tương tự về SO về chủ đề này.

Cập nhật Cảm ơn câu trả lời. Một trong những điều quan trọng nhất đối với tôi là xác định lý do tại sao việc sử dụng cái kia là lợi thế. Tôi muốn câu trả lời bao gồm một phần của một danh sách pro/con.

+0

Bạn đang nói về điều này khi lưu trữ trong DB hoặc khi đầu ra được trả về từ phần còn lại? –

+0

Thẻ có bất kỳ thông tin nào khác ngoài tên và có thể là ID không? –

+0

Thẻ chỉ chứa giá trị chuỗi. Câu hỏi này chạm vào cả thiết kế RESTful và lưu trữ DB - tôi đã cập nhật câu hỏi của mình để phản ánh. –

Trả lời

6

tl; dr

Xét yêu cầu của bạn, IMO bạn nên lưu trữ tags như nguồn lực và API của bạn nên trả lại notes với các thẻ như tính nhúng.


thiết kế cơ sở dữ liệu

Giữ notestags như bộ sưu tập riêng biệt (hoặc bảng). Vì bạn có nhiều ghi chú và nhiều thẻ và xem xét thực tế rằng chức năng cốt lõi phụ thuộc vào việc tìm kiếm/tự động hoàn tất trên các tags, điều này sẽ cải thiện hiệu suất khi tìm kiếm notes cho tags cụ thể. Một thiết kế rất cơ bản có thể trông giống như:

ghi chú

{ 
    'id': 101, // noteid 
    'title': 'Note title', 
    'body': 'Some note', 
    'tags': ['tag1', 'tag2', ...] 
} 

thẻ

{ 
    'id': 'tag1', // tagid 
    'name': 'batman', 
    'description': 'the dark knight', 
    'related': ['tagx', 'tagy', ...], 
    'notes': [101, 103, ...] 
} 

Bạn có thể sử dụng related tài sản để xử lý các bản sao bằng cách thay thế tagx, tagy bởi tương tự tags.


Thiết kế API

1. Đang tìm nạp notes cho user:

GET /users/{userid}/notes 

Nhúng các tags trong đối tượng notes khi bạn xử lý tuyến đường này ở phụ trợ. Các notes đối tượng gửi API của bạn sẽ giống như thế này:

{ 
    'id': 101, 
    'title': 'Note title', 
    'body': 'Some note', 
    'tags': ['batman'] // replacing the tag1 by its name from tag collection 
} 

2. Đang tìm nạp tags cho user:

GET /users/{userid}/tags 

Nếu nó không cần thiết, bạn có thể bỏ vào gửi notes bất động sản, trong đó có số id cho số notes của bạn.

3.Xóa tags cho notes:

DELETE /users/{userid}/{noteid}/{tag} 

4. Thêm tags cho notes:

PUT /users/{userid}/{noteid}/{tag} 

quyết các vấn đề hiệu suất, lấy tags cho user cần được nhanh chóng bởi vì bạn có một bộ sưu tập riêng biệt cho cùng . Ngoài ra, việc xử lý các bản sao sẽ đơn giản hơn vì bạn có thể chỉ cần thêm tags tương tự (theo số id hoặc name) vào mảng related. Hy vọng điều này là hữu ích.


Tại sao không giữ thẻ là tài sản lồng

  • Việc thiết kế không phải là khả năng mở rộng như trường hợp trước. Nếu tags là thuộc tính lồng nhau và tag phải được chỉnh sửa hoặc một số thông tin phải được thêm vào, thì nó sẽ yêu cầu thay đổi trong tất cả notes vì nhiều notes có thể chứa cùng một tag. Trong khi, giữ tags làm tài nguyên, cùng một số notes sẽ được ánh xạ với số ids và một thay đổi duy nhất sẽ được yêu cầu trong bộ sưu tập/bảng tags.

  • Xử lý trùng lặp tags có thể không đơn giản như khi giữ chúng dưới dạng tài nguyên riêng biệt.

  • Khi tìm kiếm tags, bạn sẽ cần phải tìm kiếm tất cả các tags được nhúng bên trong mỗi note. Điều này cho biết thêm chi phí.


Lợi thế duy nhất của việc sử dụng tags là tài sản lồng IMO là nó sẽ làm cho nó dễ dàng hơn để thêm hoặc xóa tags cho một cụ thể note.

+0

Lưu ý rằng tùy thuộc vào cơ sở dữ liệu bên dưới của bạn, bạn có thể muốn có một [bảng kết hợp] (https://en.m.wikipedia.org/wiki/Associative_entity). –

+0

Một điều tôi không nhìn thấy trong câu trả lời của bạn là một lý do để lựa chọn một cách tiếp cận khác. Tại sao tôi nên coi các thẻ là tài nguyên riêng biệt? –

+0

Tôi đã thêm một vài điểm nữa để sử dụng 'thẻ' làm thuộc tính. Hy vọng điều này có ý nghĩa hơn bây giờ. –

2

Nó có thể hơi phức tạp một chút. Vì vậy, tôi chỉ có thể chia sẻ kinh nghiệm của mình với công việc Tag (trong trường hợp của chúng tôi, đó là một tính năng chính của Ứng dụng VoIP).

Trong mọi trường hợp, tất cả Tags sẽ là đối tượng duy nhất, chứa nhiều thông tin. Như bạn biết sẽ phức tạp hơn khi chuyển, nhưng bạn sẽ cần thông tin này, ví dụ bên dưới. Và chắc chắn, Json là giải pháp nhanh nhất.

type: 'notes', 
data: { 
    id: '123456789', 
    body: '...', 
    tags: [UUID1,UUID2,UUID3] 
} 

Ví dụ: bạn cần bao nhiêu thông tin. Khi bạn muốn thay đổi màu của thẻ hoặc kích thước, dựa trên Tỷ lệ thẻ, màu dựa trên việc sử dụng số, được liên kết (không giống nhau), trùng lặp, v.v.

type: 'tag', 
data: { 
    uuid: '234-se-324', 
    body: 'superhero', 
    linked: [UUID3, UUID4] 
    rate: 4.6, 
    usage: 4323 
    duplicate: [superheros, suppahero] 
} 

Như bạn có thể thấy, chúng tôi sử dụng ngay cả bản sao. Chỉ để tiết kiệm đơn hàng của mỗi Tag. Chắc chắn chúng tôi cũng chứa logic để lọc Root Root, nhưng như bạn có thể thấy từ ví dụ trên, chúng tôi cũng sử dụng giá trị trùng lặp với Roots đặc biệt, như "Superhero" và "Suppahero" giống nhau cho chúng tôi. Và bạn có thể nghĩ, đây là rất nhiều thông tin cho "autosuggest" hoặc "autocomplete", nhưng chúng tôi chưa bao giờ gặp phải vấn đề về hiệu năng (trong trường hợp, nếu sự hỗ trợ của bên sever). Và tất cả thông tin cũng quan trọng đối với mọi cách sử dụng và cũng có cả Note trong trường hợp này.

+0

Cảm ơn câu trả lời. Một điều tôi không nhìn thấy trong câu trả lời của bạn là một lý do để lựa chọn một cách tiếp cận khác. Tại sao tôi nên coi các thẻ là tài nguyên riêng biệt? –

1

Lưu thẻ dưới dạng thuộc tính lồng nhau có ý nghĩa nếu bạn muốn có tất cả dữ liệu trong cùng một hàng. Tôi sẽ cho bạn một ví dụ.

Trên hóa đơn bạn thêm các mục,

Tiêu đề, mô tả, giá cả, qty, thuế, ...

thuế trong trường hợp này có thể là: thuế GTGT 20%, do đó bạn calcualte hóa đơn với 20%, nhưng thuế một ngày thay đổi thành 22% và tất cả các hóa đơn được lưu trên DB sẽ cao hơn 2%. Trong trường hợp này, bạn thêm cột mới và bạn lưu cột đó làm số nguyên 20 và khi bạn đọc hóa đơn đó từ db, bạn sẽ nhận được tất cả dữ liệu từ một hàng, thay vì tính toán từ các bảng hoặc biến khác nhau.

Điều tương tự là với thẻ. Nếu bạn bằng cách nào đó muốn hợp nhất các bản sao, thật dễ dàng để làm điều đó với các ID thay vì các chuỗi.

Ngoài ra còn có một số yếu tố khác mà bạn có thể cân nhắc.

trong mạng xã hội, người dùng có thể có thẻ được gọi là kỹ năng, sở thích, thể thao và hơn thế nữa.Không có cách nào thực để phân biệt giữa các thẻ từ (https://github.com/mbleigh/acts-as-taggable-on)

Vì vậy, nếu bạn đang làm thẻ mà bạn sẽ tag nhiều điều bạn phải sử dụng id

Các vấn đề liên quan