J'ai une API de repos implémentée à la suite du principe qui retient simplement les documents de base et les références de ces documents howtour obtenir d'autres choses, etc. etc p>
Par exemple A / CAR / 5 Donnez-moi Modèle: blabla, user_id: 1, puis si vous avez besoin du propriétaire, vous obtiendrez / utilisateur / 1 pour obtenir des données utilisateur .. p>
De cette façon, des joints et des trucs sont évités dans dB..Toutes les choses sont reliées entre elles et des données interconnectées sur une partie du client de repos - gardant des choses simples faciles à cache / goutte cache, à l'échelle, etc. P>
Mais que se passe-t-il lorsque vous avez besoin de tri? P>
Imaginez que nous avons une vue sur Frontend pour afficher les données suivantes: Modèle de voiture, nom d'utilisateur, etc ... et vous voulez trier par nom d'utilisateur par exemple. P>
Vous ne pouvez pas vraiment dire / la voiture / 5 à trier par nom d'utilisateur car elle ne connaît que des ID utilisateur ... P>
Une option que je vois est le tri de l'utilisateur / utilisateur / liste? Sortby = nom d'utilisateur, puis interconnectant lequel de ces identifiants retournés se réfèrent en voiture. Mais cela signifie que nous devons obtenir tous les utilisateurs..et seulement utiliser la fraction de ceux qui semblent un goulot d'étranglement de performance tueur. P>
Merci pour tous les pointeurs p>
5 Réponses :
Je pense que vous essayez d'éviter de se joindre à toutes les mauvaises raisons, comme en prenant cette approche, vous allez devoir servir beaucoup plus de demandes. P>
Si vous apportez à la place toutes les informations que vous afficheriez (c'est-à-dire le côté de la base de données de jointures), les clients devront faire moins de questions et vous pourriez-vous em> faire votre tri sans avoir à (paresseux) charger tous les objets enfants. P>
L'autre option serait de ramener les objets enfants comme des éléments XML des enfants (de la même manière que les travaux de l'interface reposante de l'OpenStreetMap). Vous avez toujours un seul coup du client et vous devriez être capable d'optimiser les requêtes pour minimiser la charge sur la DB. P>
Si vous évitez toutes les jointures sur le serveur et que vous le laissez au client, vous devez également quitter le client sur le client. En effet, une jointure doit avoir lieu afin de trier les voitures par nom d'utilisateur. P>
Vous pouvez créer une autre ressource appelée Carsandowners ou similaire qui renvoie la liste jointe, à laquelle il devient raisonnable de trier sur le serveur. P>
Je commencerais en imaginant la requête reposante idéale que je voudrais écrire, par exemple: puis comprendre comment implémenter cela. P> Maintenant, votre méthode em> List em> vous donne voiture em> objets qui n'exposent pas nom d'utilisateur em> comme vous l'avez dit, mais je ne pense pas que ce problème. Tout le tri doit avoir lieu sur le serveur avant la préparation de la liste. P> Vous devez rejoindre vos objets em> objets sur utilisateur em> un point pour le faire, et il n'ya aucun moyen d'esquiver cette question. Le seul choix que vous avez est où vous le faites. P> Si vous travaillez avec un SGDBR traditionnel, il est logique de le faire au niveau de DB. P> Utilisez-vous une couche ORM entre votre API d'application et la base de données? P> P>
Eh bien, toute la persistance est derrière le reste ..
J'ai eu l'assipation que vous utilisiez orm parce que vous avez dit que vous évitéiez des jointures sur la base de données et de connecter tous vos objets dans la couche d'application de repos. Je peux voir l'attractivité de cette architecture propre simple, mais elle est probablement à la base de votre dilemme actuel. Je chercherais à compromettre cette architecture afin d'obtenir la demande de travail: ayant des processus de commande ou des vues stockés supplémentaires sur la base de données qui renvoient les données prédéfinies, fournissant toujours la mappage de l'ORM pour ces objets et laissant la sélection de l'application de repos entre les méthodes en fonction de la requête.
Tout d'abord, votre exemple maintenant, en général si Vous voulez une approche reposante du tri pour que vous puissiez faire ceci: p> dans votre exemple, vous mentionnez que vous souhaitez trier les voitures par nom d'utilisateur. Cependant, comme vous mentionnez, la collection afin que nous puissions demander la liste des voitures pour chaque individu à une URL comme Cependant, vous avez la question de potentiellement de nombreuses demandes à votre API (ce qui peut être correct en fonction de votre cas d'utilisation). p> Une autre approche, qui est probablement meilleure, est de le faire dans une demande à: p> Cela rendrait une gamme d'utilisateurs et de leurs voitures commandées par nom d'utilisateur . p> et une autre approche pourrait être: p> mais je n'aime pas cette approche autant que la précédente. Je recommanderais l'approche précédente de latérale note: vos listes doivent être paginées de manière à ce qu'il n'y ait pas la surcharge de demandes tous em > des / voiture / 5 code> devrait être la version plurielle de la ressource afin d'être reposante: voitures code> ne devrait rien savoir sur utilisateurs code>. Donc, si vous souhaitez afficher une liste de voitures et les grouper par l'utilisateur, que faites-vous? Vous avez besoin d'un moyen de récupérer ces informations. Une façon de faire cela est de boucler les utilisateurs et de demander aux voitures associées à chaque utilisateur: p> / utilisateurs / 5 / voitures code>. Ceci est connu comme une ressource imbriquée. Nous ne demandons que les voitures qui sont liées à l'utilisateur 5. P> / users / wars code>. P> utilisateurs code> lorsque vous affichez seulement une liste partielle. p>
La nommée de ressources plurielles n'est pas une exigence de repos - quelle est la nécessité est une sémantique uniforme pour les formations pour chaque ressource: ce qui signifie que toutes les ressources exposées doivent se comporter de la même manière (du point de vue du consommateur) aux méthodes de protocole disponibles (obtenir, poster, poster, Supprimer, etc ...)
Les bases de données sont conçues pour effectuer des jointures rapidement, ce qui le laissant au client ou votre application serveur n'a pas de sens pour moi. P>
Presque tout ce que j'ai lu sur le repos dit que les relations entre entités / ressources devraient être une ressource également. Par conséquent, vous devriez avoir une ressource /mydomain.com/carsandusers qui représente cette jointure / relation. P>
Ensuite, vous pouvez faire le tri sur cette ressource, comme n'importe quel autre, et il sera traité par la base de données: P>
/mydomain.com/carsandusers?sortby=username P>
Vous pouvez également appliquer un filtrage à cette ressource (et la pagination), comme toute autre ressource. P>
EDIT: P>
Selon les commentaires, il serait préférable de faire quelque chose comme ceci: P>
/ voitures? Embed = Utilisateur, Sortby = Nom d'utilisateur P> blockQuote>
Merci Eric pour le pointant sur cette sortie. P>
C'est une recette d'explosion combinatoire des points d'extrémité de l'API. Une approche reposante plus commune consiste à utiliser des paramètres pour demander des objets inlinés (des représentations essentiellement reliées). Par exemple: / albums? Incorporer = artiste code>. Ces ressources disponibles pour l'intégration peuvent avoir des liens dans une collection HYPERMEDIA LIENS CODE> pour que l'option découvrable.
Merci Eric, tandis que je suis d'accord avec votre point sur l'explosion des points de terminaison, la question ne concerne pas les objets connexes, mais sur le tri d'un ensemble basé sur la propriété d'un ensemble associé. Je ne suis pas sûr de ce que vous suggérez de résoudre ce problème particulier. Ou dites-vous que l'OP pourrait faire ceci: / voitures? Incorporer = utilisateur, Sortby = nom d'utilisateur
Oui, c'est à peu près exactement ce que je suggère.
@Ericelliott Merci de confirmer et oui, vous avez raison, c'est une meilleure approche. Je vais éditer ma réponse.