Спочатку
Відповідно до RFC 3986 §3.4 (Уніфіковані ідентифікатори ресурсів § (Синтаксичні компоненти) | Запит
3.4 Запит
Компонент запиту містить неієрархічні дані, які поряд із даними в компоненті шляху (Розділ 3.3) служать для ідентифікації ресурсу в межах схеми URI та органу іменування (якщо він є).
Компоненти запиту призначені для пошуку неієрархічних даних; є кілька речей, більш ієрархічних за своєю природою, ніж генеалогічне дерево! Ergo - незалежно від того, чи вважаєте ви це "REST-y" чи ні , щоб відповідати форматам, протоколам та структурам та для розробки систем в Інтернеті, ви не повинні використовувати рядок запитів для ідентифікації цієї інформації.
REST не має нічого спільного з цим визначенням.
Перш ніж звертатись до ваших конкретних питань, ваш параметр запиту "пошук" погано названий. Краще було б ставитися до сегменту запитів як до словника пар ключових значень.
Ваш рядок запиту може бути більш відповідним чином визначений як
?first_name={firstName}&last_name={lastName}&birth_date={birthDate}
тощо.
Щоб відповісти на ваші конкретні запитання
1) Який дизайн API більш ВІДКРИТИЙ і чому? Семантично вони означають і поводяться однаково. Останній ресурс в URI - це "діти", що фактично передбачає, що клієнт працює на дитячому ресурсі.
Я не думаю, що це так чітко, як ви, здається, вірите.
Жоден із цих ресурсних інтерфейсів не є RESTful. Основним умовою для RESTful архітектурного стилю є те , що стан додатки переходи повинні бути передані з сервера в гіпермедіа. Люди трудилися над структурою URI, щоб зробити їх якось "RESTful URI", але формальна література, що стосується REST, насправді мало що про це говорить. Моя особиста думка полягає в тому, що значна частина мета-дезінформації про REST була опублікована з наміром порушити старі шкідливі звички. (Побудова справді "RESTful" системи - це фактично велика робота. Галузь перейшла на "REST" і заповнила деякі ортогональні проблеми з безглуздими кваліфікаціями та обмеженнями.)
Що говорить література REST, це те, що якщо ви збираєтеся використовувати протокол HTTP в якості протоколу програми, ви повинні дотримуватися формальних вимог специфікацій протоколу, і ви не можете "створювати http, коли ви йдете, і все ще заявляєте, що використовуєте http" ; якщо ви збираєтеся використовувати URI для ідентифікації своїх ресурсів, ви повинні дотримуватися формальних вимог специфікацій щодо URI / URL-адрес.
На ваше питання безпосередньо звертається RFC3986 §3.4, яку я зв'язав вище. Суть у цьому питанні полягає в тому, що, хоча відповідний URI недостатній, щоб вважати API "RESTful", якщо ви хочете, щоб ваша система фактично була "RESTful" і ви використовуєте HTTP та URI, ви не можете ідентифікувати ієрархічні дані через рядок запиту, оскільки:
3.4 Запит
Компонент запиту містить неієрархічні дані
... це так просто.
2) Які плюси і мінуси для кожного з точки зору зрозумілості з точки зору клієнта та ремонтопридатності з точки зору дизайнера.
«Плюси» перших двох у тому, що вони на правильному шляху . «Мінуси» третього полягає в тому, що він, здається, вирівнюється неправильно.
Що стосується вашої зрозумілості та ремонтопридатності, вони, безумовно, суб'єктивні і залежать від рівня розуміння клієнта розробника та дизайнерських відсіків дизайнера. Специфікація URI - це остаточна відповідь щодо форматування URI. Ієрархічні дані повинні бути представлені на шляху та з параметрами шляху. Неієрархічні дані повинні бути представлені у запиті. Фрагмент є складнішим, оскільки його семантика конкретно залежить від типу носія запитуваного представлення. Отже, щоб вирішити "зрозумілий" компонент вашого запитання, я спробую точно перекласти те, що говорять ваші перші два URI. Потім я спробую представити те, що ви говорите, що намагаєтеся виконати з дійсними URI.
Переклад дословних URI на їх семантичне значення
/myservice/api/v1/grandparents/{grandparentID}/parents/children?search={text}
Це говорить про батьків бабусь і дідусів і бабусь, знайдіть їхню дитину. search={text}
Те, що ви сказали зі своїм URI, узгоджується лише тоді, коли шукаєте братів та сестер. З вашими "бабусями та дідусями, батьками, дітьми" ви виявили, що "бабуся і дідусь" піднімалися на покоління до їх батьків, а потім поверталися до "бабусь і дідусів", дивлячись на дітей батьків.
/myservice/api/v1/parents/{parentID}/children?search={text}
Це говорить про те, що для батьків , ідентифікованих {ParentID}, знайти їх дитина , яка має ?search={text}
це ближче , щоб виправити те, що ви бажаєте , і являє собою відносини між батьками> дитиною , який , ймовірно , може бути використаний для моделювання всього API. Щоб моделювати це таким чином, на клієнта покладається тягар, який визнає, що якщо у них є "бабуся і дід", то між ідентифікатором, який вони мають, і тією частиною сімейного графіка, яку вони бажають бачити, існує шар непрямості. Щоб знайти "дитину" за допомогою "grandparentId", ви можете зателефонувати у вашу /parents/{parentID}/children
службу, а потім пророкувати дитину, яка повертається, шукати їх дітей за ідентифікатором вашої особи.
Реалізація ваших вимог як URI
Якщо ви хочете моделювати більш розширюваний ідентифікатор ресурсу, який може ходити по дереву, я можу придумати декілька способів, як ви це зможете досягти.
1) Перше, що я вже згадував. Представити графік "Люди" у вигляді складеної структури. Кожна людина має посилання на покоління над нею через шлях батьків і на покоління під ним через свій Дітячий шлях.
/Persons/Joe/Parents/Mother/Parents
був би способом захопити Джо-бабусю та дідуся по матері.
/Persons/Joe/Parents/Parents
був би способом схопити всіх бабусь і дідусів Джо.
/Persons/Joe/Parents/Parents?id={Joe.GrandparentID}
схопив би дідуськи Джо і мав ідентифікатор, який у вас в руках.
і все це матиме сенс (зауважте, що тут може бути покарання за ефективність залежно від завдання, вимушуючи dfs на сервер через відсутність ідентифікації гілки в шаблоні "Батьки / батьки / батьки"). можливість підтримувати будь-яку довільну кількість поколінь. Якщо ви чомусь хочете шукати 8 поколінь, ви могли б це уявити
/Persons/Joe/Parents/Parents/Parents/Parents/Parents/Parents/Parents/Parents?id={Joe.NotableAncestor}
але це призводить до другого домінуючого варіанту представлення цих даних: через параметр шляху.
2) Використовуйте параметри шляху для "запиту на ієрархію". Ви можете розробити наступну структуру, щоб полегшити навантаження на споживачів і все ще мати API, який має сенс.
Оглянути 147 поколінь, що представляє цей ідентифікатор ресурсу з параметрами шляху
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor}
Щоб знайти Джо у його Великого Дідуся, Ви можете переглянути графік відомої кількості поколінь для ІД Джо.
/Persons/JoesGreatGrandparent/Children;generations=3?id={Joe.Id}
Головне, що слід звернути увагу на ці підходи, - це те, що без додаткової інформації в ідентифікаторі та запиті слід очікувати, що перший URI витягує особу 147 поколінь від Джо з ідентифікатором Joe.NotableAncestor. Ви повинні очікувати, що другий поверне Джо. Припустимо, що ви дійсно хочете, щоб ваш клієнт, що дзвонить, міг отримати весь набір вузлів та їх зв’язки між кореневою Особою та кінцевим контекстом вашого URI. Ви можете зробити це з тим самим URI (з деяким додатковим оформленням) та встановивши Accept text/vnd.graphviz
на ваш запит, який є носієм, зареєстрованим IANA для .dot
представлення графіків. За допомогою цього змініть URI на
/Persons/Joe/Parents;generations=147?id={Joe.NotableAncestor.Id}#directed
з заголовком запиту HTTP,
Accept: text/vnd.graphviz
і ви можете мати клієнтів досить чітко повідомляти про те, що вони хочуть спрямований графік ієрархії поколінь між Джо та 147 поколіннями до того, коли це 14-е покоління родовідника містить людину, ідентифіковану як "Помітний прародитель" Джо.
Я не впевнений, що в тексті / vnd.graphviz є якийсь заздалегідь визначений семантичний фрагмент для його фрагменту, я не міг знайти жодного в пошуку інструкції. Якщо цей тип носія насправді має заздалегідь визначену фрагментну інформацію, то для створення відповідного URI слід дотримуватися його семантики. Але якщо ці семантики не визначені заздалегідь, специфікація URI зазначає, що семантика ідентифікатора фрагмента не обмежена і замість цього визначена сервером, що робить це використання дійсним.
3) Для чого насправді використовуються рядки запитів, окрім «фільтрації» на вашому ресурсі? Якщо перейти з першим підходом, параметр фільтра вбудовується в сам URI як параметр шляху замість параметра рядка запиту.
Я вважаю, що я вже ретельно побив це до смерті, але рядки запитів не для "фільтрації" ресурсів. Вони призначені для ідентифікації вашого ресурсу з неієрархічних даних. Якщо ви прорахували свою ієрархію своїм шляхом, перейшовши,
/person/{id}/children/
і ви хочете визначити конкретну дитину або певний набір дітей, ви скористаєтесь деяким атрибутом, який стосується набору, який ви ідентифікуєте, і включите його до запиту.