Đầu tiên
Theo RFC 3986 §3.4 (Số nhận dạng tài nguyên đồng nhất § (Thành phần cú pháp) | Truy vấn
3,4 Truy vấn
Thành phần truy vấn chứa dữ liệu không phân cấp, cùng với dữ liệu trong thành phần đường dẫn (Mục 3.3), phục vụ để xác định tài nguyên trong phạm vi của lược đồ và quyền đặt tên của URI (nếu có).
Các thành phần truy vấn là để lấy dữ liệu không phân cấp; Có một vài thứ trong tự nhiên hơn là một cây gia đình! Ergo - bất kể bạn nghĩ đó là "REST-y" hay không - để tuân thủ các định dạng, giao thức và khung của và để phát triển hệ thống trên internet, bạn không được sử dụng chuỗi truy vấn để xác định thông tin này.
REST không có gì để làm với định nghĩa này.
Trước khi giải quyết các câu hỏi cụ thể của bạn, tham số truy vấn "tìm kiếm" của bạn được đặt tên kém. Tốt hơn là coi phân đoạn truy vấn của bạn là một từ điển của các cặp khóa-giá trị.
Chuỗi truy vấn của bạn có thể được định nghĩa phù hợp hơn là
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
Vân vân.
Để trả lời các câu hỏi cụ thể của bạn
1) Thiết kế API nào RESTful hơn và tại sao? Về mặt ngữ nghĩa, chúng có nghĩa và hành xử theo cùng một cách. Tài nguyên cuối cùng trong URI là "trẻ em", ngụ ý hiệu quả rằng máy khách đang hoạt động trên tài nguyên trẻ em.
Tôi không nghĩ rằng điều này rõ ràng như bạn tin tưởng.
Không có giao diện tài nguyên nào trong số này là RESTful. Điều kiện tiên quyết chính cho phong cách kiến trúc RESTful là các chuyển đổi Trạng thái ứng dụng phải được truyền thông từ máy chủ dưới dạng hypermedia. Mọi người đã làm việc với cấu trúc của các URI để biến chúng thành "URI RESTful" bằng cách nào đó nhưng tài liệu chính thức về REST thực sự có rất ít điều để nói về điều này. Ý kiến cá nhân của tôi là phần lớn thông tin sai lệch về REST đã được xuất bản với mục đích phá bỏ những thói quen xấu, cũ. .
Điều mà tài liệu REST nói là nếu bạn định sử dụng HTTP làm giao thức ứng dụng của mình, bạn phải tuân thủ các yêu cầu chính thức về thông số kỹ thuật của giao thức và bạn không thể "tạo ra http khi bạn đi và vẫn tuyên bố rằng bạn đang sử dụng http" ; nếu bạn định sử dụng URI để xác định tài nguyên của mình, bạn phải tuân thủ các yêu cầu chính thức của thông số kỹ thuật về URI / URL.
Câu hỏi của bạn được giải quyết trực tiếp bởi RFC3986 §3.4, mà tôi đã liên kết ở trên. Điểm mấu chốt của vấn đề này là mặc dù URI tuân thủ không đủ để xem xét API "RESTful", nếu bạn muốn hệ thống của mình thực sự là "RESTful" và bạn đang sử dụng HTTP và URI, thì bạn không thể xác định dữ liệu phân cấp thông qua chuỗi truy vấn vì:
3,4 Truy vấn
Thành phần truy vấn chứa dữ liệu không phân cấp
...Nó đơn giản như vậy.
2) Những ưu và nhược điểm của mỗi khía cạnh về mức độ dễ hiểu theo quan điểm của khách hàng và khả năng duy trì từ quan điểm của nhà thiết kế.
"Ưu điểm" của hai người đầu tiên là họ đang đi đúng hướng . "Nhược điểm" của cái thứ ba là nó dường như bị sai.
Theo như sự hiểu biết và khả năng bảo trì của bạn, những điều đó chắc chắn là chủ quan và phụ thuộc vào mức độ hiểu của nhà phát triển khách hàng và các nhóm thiết kế của nhà thiết kế. Đặc tả URI là câu trả lời dứt khoát về cách các URI được định dạng. Dữ liệu phân cấp được cho là được thể hiện trên đường dẫn và với các tham số đường dẫn. Dữ liệu không phân cấp được cho là được thể hiện trong truy vấn. Đoạn này phức tạp hơn, bởi vì ngữ nghĩa của nó phụ thuộc cụ thể vào loại phương tiện truyền thông của đại diện được yêu cầu. Vì vậy, để giải quyết thành phần "dễ hiểu" trong câu hỏi của bạn, tôi sẽ cố gắng dịch chính xác hai URI đầu tiên của bạn đang thực sự nói gì. Sau đó, tôi sẽ cố gắng thể hiện những gì bạn nói bạn đang cố gắng thực hiện với các URI hợp lệ.
Dịch các URI nguyên văn của bạn sang nghĩa ngữ nghĩa của chúng
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
Điều này nói với cha mẹ của ông bà, tìm con của họ có search={text}
những gì bạn nói với URI của bạn chỉ mạch lạc nếu tìm kiếm anh chị em của ông bà. Với "ông bà, cha mẹ, con cái", bạn đã tìm thấy một "ông bà" đã đi lên một thế hệ với cha mẹ của họ và sau đó quay trở lại thế hệ "ông bà" bằng cách nhìn vào con cái của cha mẹ.
/myservice/api/v1/parents/{parentID}/children?search={text}
Điều này nói rằng đối với cha mẹ được xác định bởi {ParentID}, hãy tìm con của họ Có điều ?search={text}
này gần đúng hơn với những gì bạn muốn và thể hiện mối quan hệ cha mẹ-> con có thể được sử dụng để mô hình hóa toàn bộ API của bạn. Để mô hình hóa nó theo cách này, gánh nặng được đặt lên khách hàng để nhận ra rằng nếu họ có "ông bà", thì có một lớp không xác định giữa ID họ có và phần biểu đồ gia đình họ muốn xem. Để tìm "đứa con" của "grandparentId", bạn có thể gọi /parents/{parentID}/children
dịch vụ của mình và sau đó thông báo cho đứa trẻ được trả lại, tìm kiếm con của chúng để nhận dạng người của bạn.
Việc thực hiện các yêu cầu của bạn dưới dạng URI
Nếu bạn muốn mô hình hóa một mã định danh tài nguyên có thể mở rộng hơn có thể đi trên cây, tôi có thể nghĩ ra một số cách bạn có thể thực hiện được.
1) Cái đầu tiên, tôi đã ám chỉ. Biểu diễn biểu đồ "Con người" dưới dạng cấu trúc tổng hợp. Mỗi người có một tham chiếu đến thế hệ bên trên nó thông qua con đường Cha mẹ của nó và đến một thế hệ bên dưới nó thông qua con đường Con cái của nó.
/Persons/Joe/Parents/Mother/Parents
sẽ là một cách để lấy ông bà ngoại của Joe.
/Persons/Joe/Parents/Parents
sẽ là một cách để lấy tất cả ông bà của Joe.
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
sẽ lấy ông bà của Joe có số nhận dạng bạn có trong tay.
và tất cả đều có ý nghĩa (lưu ý rằng có thể có hình phạt hiệu suất ở đây tùy theo nhiệm vụ bằng cách buộc một dfs trên máy chủ do thiếu nhận dạng chi nhánh trong mẫu "Cha mẹ / Cha mẹ / Cha mẹ".) Bạn cũng được hưởng lợi từ việc có khả năng hỗ trợ bất kỳ số lượng thế hệ tùy ý. Nếu, vì một số lý do, bạn mong muốn tìm kiếm 8 thế hệ, bạn có thể đại diện cho điều này như
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
nhưng điều này dẫn đến tùy chọn chi phối thứ hai để thể hiện dữ liệu này: thông qua một tham số đường dẫn.
2) Sử dụng tham số đường dẫn để "truy vấn phân cấp" Bạn có thể phát triển cấu trúc sau để giúp giảm bớt gánh nặng cho người tiêu dùng và vẫn có API có ý nghĩa.
Để nhìn lại 147 thế hệ, việc biểu thị định danh tài nguyên này bằng các tham số đường dẫn cho phép bạn thực hiện
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
Để xác định vị trí của Joe từ Ông cố của anh ấy, bạn có thể nhìn xuống biểu đồ một số thế hệ đã biết cho Id của Joe.
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
Điều quan trọng cần lưu ý với các cách tiếp cận này là không có thêm thông tin trong mã định danh và yêu cầu, bạn nên mong đợi rằng URI đầu tiên đang truy xuất một thế hệ 147 người từ Joe với mã định danh Joe.NotableAncestor. Bạn nên mong đợi người thứ hai lấy Joe. Giả sử rằng những gì bạn thực sự muốn là cho máy khách gọi của bạn có thể truy xuất toàn bộ tập hợp các nút và mối quan hệ của chúng giữa Người gốc và bối cảnh cuối cùng của URI của bạn. Bạn có thể làm điều đó với cùng một URI (với một số trang trí bổ sung) và đặt Chấp nhận text/vnd.graphviz
theo yêu cầu của bạn, đó là loại phương tiện đã đăng ký IANA cho .dot
biểu diễn đồ thị. Cùng với đó, thay đổi URI thành
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
với Tiêu đề yêu cầu HTTP
Accept: text/vnd.graphviz
và bạn có thể có khách hàng giao tiếp khá rõ ràng rằng họ muốn biểu đồ được định hướng của hệ thống phân cấp thế hệ giữa Joe và 147 thế hệ trước trong đó thế hệ tổ tiên thứ 147 chứa một người được xác định là "Tổ tiên đáng chú ý" của Joe.
Tôi không chắc chắn nếu text / vnd.graphviz có bất kỳ ngữ nghĩa được xác định trước cho đoạn của nó hay không, tôi không thể tìm thấy gì trong tìm kiếm hướng dẫn. Nếu loại phương tiện đó thực sự có thông tin phân đoạn được xác định trước, thì ngữ nghĩa của nó phải được tuân theo để tạo URI phù hợp. Nhưng, nếu các ngữ nghĩa đó không được xác định trước, đặc tả URI nói rằng ngữ nghĩa của mã định danh phân đoạn không bị ràng buộc và thay vào đó được xác định bởi máy chủ, làm cho việc sử dụng này hợp lệ.
3) Chuỗi truy vấn thực sự được sử dụng để làm gì, ngoài "lọc" trên tài nguyên của bạn? Nếu bạn đi theo cách tiếp cận đầu tiên, tham số bộ lọc được nhúng vào chính URI dưới dạng tham số đường dẫn thay vì tham số chuỗi truy vấn.
Tôi tin rằng tôi đã hoàn toàn đánh bại điều này đến chết, nhưng các chuỗi truy vấn không dành cho tài nguyên "lọc". Chúng là để xác định tài nguyên của bạn từ dữ liệu không phân cấp. Nếu bạn đã đi sâu vào hệ thống phân cấp của mình bằng con đường của mình bằng cách đi
/person/{id}/children/
và bạn muốn xác định một đứa trẻ cụ thể hoặc một nhóm trẻ cụ thể , bạn sẽ sử dụng một số thuộc tính áp dụng cho tập hợp bạn đang xác định và đưa nó vào trong truy vấn.