RESTful URL design for search

Szukam rozsądnego sposobu na reprezentowanie wyszukiwań jako RESTful Url.

Konfiguracja: mam dwa modele, Samochody i garaże, gdzie samochody mogą być w garażach. Więc moje adresy URL wyglądają tak:

/car/xxxx
  xxx == car id
  returns car with given id

/garage/yyy
  yyy = garage id
  returns garage with given id
Samochód może istnieć samodzielnie (stąd / samochód) lub może istnieć w garażu. Jaki jest właściwy sposób reprezentowania, powiedzmy, wszystkich samochodów w danym garażu? Coś w stylu:
/garage/yyy/cars     ?
A co z połączeniem samochodów w garażu yyy i zzz?

Jaki jest właściwy sposób reprezentowania wyszukiwania dla samochodów z pewnymi atrybutami? Powiedz: Pokaż mi wszystkie niebieskie sedany z 4 drzwiami:

/car/search?color=blue&type=sedan&doors=4

Czy powinno być /Samochody zamiast?

Użycie "Szukaj" wydaje się tam niewłaściwe - jaki jest lepszy sposób / termin? Powinno być:

/cars/?color=blue&type=sedan&doors=4

Czy parametry wyszukiwania powinny być częścią PATHINFO lub QUERYSTRING?

Krótko mówiąc, szukam dobrego przewodnika / samouczka do projektowania REST url między modelami i wyszukiwania.

[[6]] [Update] podoba mi się odpowiedź Justina, ale nie pokrywa przypadek wyszukiwania w wielu polach:
/cars/color:blue/type:sedan/doors:4
Czy coś w tym stylu. How do we go from
/cars/color/blue

Do sprawy multiple field?

 377
Author: Parand, 2008-10-16

12 answers

Do wyszukiwania użyj querystrings. To jest doskonale wypoczęte:

/cars?color=blue&type=sedan&doors=4

Zaletą regularnych zapytań jest to, że są one standardowe i szeroko rozumiane oraz że mogą być generowane z form-get.

 386
Author: pbreitenbach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-14 13:06:08

Projekt RESTful pretty URL polega na wyświetleniu zasobu opartego na strukturze (struktura katalogowa, Data: artykuły/2005/5/13, obiekt i jego atrybuty,..), ukośnik / wskazuje strukturę hierarchiczną, zamiast tego użyj -id.

Struktura hierarchiczna

Ja osobiście wolę:

/garage-id/cars/car-id
/cars/car-id   #for cars not in garages

Jeśli użytkownik usunie część /car-id, wyświetli cars preview - intuicyjny. Użytkownik dokładnie wie, gdzie w drzewie się znajduje, Na co patrzy. Wie od pierwszego spojrzenia, że garaże i samochody są w związku. /car-id oznacza również, że należy do siebie w przeciwieństwie do /car/id.

Wyszukiwanie

Searchquery jest OK, jak to jest, jest tylko twoje preferencje, co należy wziąć pod uwagę. Zabawna część pojawia się podczas łączenia wyszukiwania (patrz poniżej).

/cars?color=blue;type=sedan   #most prefered by me
/cars;color-blue+doors-4+type-sedan   #looks good when using car-id
/cars?color=blue&doors=4&type=sedan   #I don't recommend using &*

Lub w zasadzie wszystko, co nie jest ukośnikiem, jak wyjaśniono powyżej.
Wzór: /cars[?;]color[=-:]blue[,;+&], * choć nie używałbym znaku & Jak to jest nie do rozpoznania z tekstu na pierwszy rzut oka.

** Czy wiesz, że przechodzenie obiektu JSON w URI jest spokojne? **

Lista opcji

/cars?color=black,blue,red;doors=3,5;type=sedan   #most prefered by me
/cars?color:black:blue:red;doors:3:5;type:sedan
/cars?color(black,blue,red);doors(3,5);type(sedan)   #does not look bad at all
/cars?color:(black,blue,red);doors:(3,5);type:sedan   #little difference

Możliwe cechy?

Negate search strings (!)
Aby przeszukać dowolne samochody, ale Nie czarny i czerwony:
?color=!black,!red
color:(!black,!red)

Połączone wyszukiwania
Szukaj czerwony lub niebieski lub Czarne samochody z 3 drzwi w garażach id 1..20 lub 101..103 lub 999 ale Nie 5 /garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
Następnie można konstruować bardziej złożone zapytania wyszukiwania. (Spójrz na dopasowanie atrybutu CSS3 dla idei dopasowania podciągów. Np. wyszukiwanie użytkowników zawierających " bar " user*=bar.)

Podsumowanie

W każdym razie, to może być dla Ciebie najważniejsza część, ponieważ możesz to zrobić jak chcesz, po prostu należy pamiętać, że RESTful URI reprezentuje strukturę łatwo zrozumiałą np. katalogową /directory/file, /collection/node/item, daty /articles/{year}/{month}/{day}.. A gdy pominiesz którykolwiek z ostatnich segmentów, od razu wiesz, co otrzymasz.

Więc.., wszystkie te znaki są dozwolone niekodowane :

  • a-zA-Z0-9_.-~
  • zarezerwowane: ;/?:@=&$-_.+!*'(),
  • niebezpieczne*: <>"#%{}|\^~[]`

*dlaczego niebezpieczne i dlaczego raczej powinno być zakodowane: RFC 1738 zobacz 2.2

RFC 3986 patrz 2.2
Pomimo tego, co wcześniej powiedziałem, tutaj jest powszechne rozróżnienie ograniczników, co oznacza, że niektóre " są " {45]} ważniejsze od innych.

  • ogólne ograniczniki: :/?#[]@
  • podrozdziały: !$&'()*+,;=

Więcej informacji:
Hierarchia: zobacz 2.3, Zobacz też 1.2.3
składnia parametru ścieżki url
atrybut CSS3 dopasowanie
IBM: RESTful Web services-podstawy
Uwaga: RFC 1738 został zaktualizowany przez RFC 3986

 109
Author: Qwerty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-03 09:46:33

Chociaż posiadanie parametrów w ścieżce ma pewne zalety, są, IMO, pewne czynniki przeważające.

  • Nie wszystkie znaki potrzebne do wyszukiwania są dozwolone w adresie URL. Większość znaków interpunkcyjnych i Unicode musi być zakodowana jako parametr ciągu zapytania. Zmagam się z tym samym problemem. Chciałbym użyć XPath w adresie URL, ale nie cała składnia XPath jest zgodna ze ścieżką URI. Więc dla prostych ścieżek /cars/doors/driver/lock/combination byłoby właściwe zlokalizowanie element "combination " w dokumencie XML drzwi kierowcy. Ale nie jest tak przyjazny.

  • Istnieje różnica między filtrowaniem zasobu na podstawie jednego z jego atrybutów a określaniem zasobu.

    Na przykład, ponieważ

    /cars/colors zwraca listę wszystkich kolorów dla wszystkich samochodów (zwracany zasób jest kolekcją obiektów kolorów)

    /cars/colors/red,blue,green zwróci listę kolorowych obiektów, które są czerwone, niebieskie lub zielone, a nie kolekcję samochodów.

    To samochody powrotne, ścieżka będzie

    /cars?color=red,blue,green lub /cars/search?color=red,blue,green

  • Parametry w ścieżce są trudniejsze do odczytania, ponieważ pary nazwa / wartość nie są odizolowane od reszty ścieżki, która nie jest parami nazwa / wartość.

Ostatni komentarz. Wolę /garages/yyy/cars (Zawsze w liczbie mnogiej) od /garage/yyy/cars (być może była to literówka w oryginalnej odpowiedzi), ponieważ pozwala uniknąć zmiany ścieżki między liczbą pojedynczą a mnogą. Dla słów z dodanym "s" zmiana nie jest taka zła, ale zmiana /person/yyy/friends do /people/yyy wydaje się uciążliwe.

 34
Author: Doug Domeny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 13:49:37

Aby rozwinąć odpowiedź Piotra - możesz sprawić, że wyszukiwanie będzie zasobem pierwszej klasy:

POST    /searches          # create a new search
GET     /searches          # list all searches (admin)
GET     /searches/{id}     # show the results of a previously-run search
DELETE  /searches/{id}     # delete a search (admin)

Zasób wyszukiwania miałby pola dla koloru, modelu marki, stanu garażowanego itp. i może być określony w XML, JSON lub dowolnym innym formacie. Podobnie jak zasób samochodu i garażu, możesz ograniczyć dostęp do wyszukiwania na podstawie uwierzytelniania. Użytkownicy, którzy często przeprowadzają te same wyszukiwania, mogą przechowywać je w swoich profilach, dzięki czemu nie trzeba ich ponownie tworzyć. Adresy URL będą na tyle krótkie, że w wielu przypadki mogą być łatwo wymieniane za pośrednictwem poczty e-mail. Te zapisane wyszukiwania mogą być podstawą niestandardowych kanałów RSS i tak dalej.

Istnieje wiele możliwości korzystania z wyszukiwań, gdy myślisz o nich jako o zasobach.

[[1]}idea jest wyjaśniona bardziej szczegółowo w tym Railscast .
 30
Author: Rich Apodaca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-29 16:03:41

Odpowiedź Justina jest prawdopodobnie droga do zrobienia, chociaż w niektórych aplikacjach może mieć sens, aby rozważyć konkretne wyszukiwanie jako zasób sam w sobie, na przykład, jeśli chcesz wspierać nazwane zapisane wyszukiwania:

/search/{searchQuery}

Lub

/search/{savedSearchName}
 11
Author: Peter Hilton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-16 10:52:48

To nie jest odpoczynek. Nie można zdefiniować identyfikatorów URI dla zasobów w interfejsie API. Nawigacja zasobów musi być oparta na hipertekście. Jest w porządku, jeśli chcesz dość Uri i duże ilości sprzężenia, ale po prostu nie nazywaj go REST, ponieważ bezpośrednio narusza ograniczenia architektury RESTful.

Zobacz ten Artykuł autorstwa wynalazcy odpoczynku.

 5
Author: aehlke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-20 18:52:20

Używam dwóch podejść do realizacji wyszukiwania.

1) najprostszy przypadek, do odpytywania powiązanych elementów i do nawigacji.

    /cars?q.garage.id.eq=1

Oznacza to, że odpytuje samochody, które mają identyfikator garażu równy 1.

Możliwe jest również tworzenie bardziej złożonych wyszukiwań:

    /cars?q.garage.street.eq=FirstStreet&q.color.ne=red&offset=300&max=100
Samochody we wszystkich garażach w FirstStreet, które nie są czerwone (3 strona, 100 elementów na stronę).

2) złożone zapytania są uważane za regularne zasoby, które są tworzone i mogą być odzyskane.

    POST /searches  => Create
    GET  /searches/1  => Recover search
    GET  /searches/1?offset=300&max=100  => pagination in search

Ciało postu do tworzenia wyszukiwania jest następujące:

    {  
       "$class":"test.Car",
       "$q":{
          "$eq" : { "color" : "red" },
          "garage" : {
             "$ne" : { "street" : "FirstStreet" }
          }
       }
    }

Opiera się na Grails (criteria DSL): http://grails.org/doc/2.4.3/ref/Domain%20Classes/createCriteria.html

 5
Author: user2108278,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-10 14:38:12

Choć podoba mi się odpowiedź Justina, to uważam, że dokładniej reprezentuje filtr, a nie wyszukiwanie. Co jeśli chcę wiedzieć o samochodach z nazwami zaczynającymi się od cam?

Ja to widzę tak, że możesz to wbudować w sposób, w jaki radzisz sobie z konkretnymi zasobami:
/ samochody / cam*

Możesz też po prostu dodać go do filtra:
/ samochody / drzwi / 4 / name/cam* / colors / red, blue,green

Osobiście wolę to drugie, jednak w żadnym wypadku nie jestem ekspertem od odpoczynku (po pierwszym usłyszeniu z tego tylko 2 tygodnie temu...)

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 15:02:54

Dodatkowo proponowałbym również:

/cars/search/all{?color,model,year}
/cars/search/by-parameters{?color,model,year}
/cars/search/by-vendor{?vendor}

Tutaj, Search jest uważany za zasoby potomne Cars zasobów.

 1
Author: aux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-12 21:49:04

RESTful nie zaleca używania czasowników w URL ' s / cars / search is not restful. Właściwym sposobem filtrowania/wyszukiwania / paginowania API są parametry zapytań. Jednak mogą wystąpić przypadki, gdy trzeba będzie złamać normę. Na przykład, jeśli szukasz w wielu zasobach, to musisz użyć czegoś takiego jak / search?q=query

Możesz przejść http://saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices / aby zrozumieć najlepsze praktyki projektowania RESTful API ' s

 0
Author: java_geek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-06 06:53:25

Istnieje wiele dobrych opcji dla twojej sprawy tutaj. Mimo to powinieneś rozważyć użycie ciała POST.

Łańcuch zapytania jest idealny dla Twojego przykładu, ale jeśli masz coś bardziej skomplikowanego, np. dowolną długą listę elementów lub warunkowe wartości logiczne, możesz zdefiniować post jako dokument, który klient wysyła przez POST.

Pozwala to na bardziej elastyczny opis wyszukiwania, a także pozwala uniknąć limitu długości adresu URL serwera.

 0
Author: estani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-15 14:45:36

Moja rada byłaby taka:

/garages
  Returns list of garages (think JSON array here)
/garages/yyy
  Returns specific garage
/garage/yyy/cars
  Returns list of cars in garage
/garages/cars
  Returns list of all cars in all garages (may not be practical of course)
/cars
  Returns list of all cars
/cars/xxx
  Returns specific car
/cars/colors
  Returns lists of all posible colors for cars
/cars/colors/red,blue,green
  Returns list of cars of the specific colors (yes commas are allowed :) )

Edit:

/cars/colors/red,blue,green/doors/2
  Returns list of all red,blue, and green cars with 2 doors.
/cars/type/hatchback,coupe/colors/red,blue,green/
  Same idea as the above but a lil more intuitive.
/cars/colors/red,blue,green/doors/two-door,four-door
  All cars that are red, blue, green and have either two or four doors.
Mam nadzieję, że to Ci podpowie. Zasadniczo API Rest powinno być łatwo wykrywalne i powinno umożliwiać przeglądanie danych. Kolejną zaletą korzystania z adresów URL, a nie ciągów zapytań, jest możliwość wykorzystania natywnych mechanizmów buforowania, które istnieją na serwerze WWW dla ruchu HTTP.

Oto link do strony opisującej zło ciągów zapytań w REST: http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful

Użyłem cache Google, ponieważ normalna strona nie działała dla mnie tutaj jest ten link, jak również: http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful

 -3
Author: Justin Bozonier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 14:17:48