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?
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.
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
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.
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 .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}
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.
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
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...)
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.
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
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.
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
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