190 votes

Quelle est la meilleure méthode RESTful pour retourner le nombre total d'éléments dans un objet ?

Je développe un service API REST pour un grand site de réseautage social dans lequel je suis impliqué. Jusqu'à présent, cela fonctionne très bien. Je peux émettre des GET , POST , PUT y DELETE à des URL d'objets et affectent mes données. Cependant, ces données sont paginées (limitées à 30 résultats à la fois).

Quel serait le meilleur moyen RESTful d'obtenir le nombre total de membres, par exemple, via mon API ?

Actuellement, j'envoie des requêtes à une structure URL comme la suivante :

  • /api/membres - Renvoie une liste de membres (30 à la fois comme indiqué ci-dessus)
  • /api/membres/1 - Affecte un seul membre, en fonction de la méthode de requête utilisée

Ma question est la suivante : comment puis-je utiliser une structure URL similaire pour obtenir le nombre total de membres dans mon application ? Il est évident qu'en demandant seulement le id (similaire à l'API Graph de Facebook) et le comptage des résultats serait inefficace car seule une tranche de 30 résultats serait renvoyée.

2voto

Frank Points 1419

Vous pouvez envisager counts en tant que ressource. L'URL serait alors :

/api/counts/member

2voto

Discussion intéressante concernant la conception de l'API REST pour le comptage de plusieurs objets : https://groups.google.com/g/api-craft/c/qbI2QRrpFew/m/h30DYnrqEwAJ?pli=1

En tant que consommateur de l'API, je m'attends à ce que chaque valeur de comptage soit représentée de la manière suivante soit représentée comme une sous-ressource de la ressource comptabilisable (c'est-à-dire GET /tasks/count pour un décompte des tâches), soit comme un champ dans une plus grande agrégation plus importante de métadonnées relatives à la ressource concernée (c.-à-d. GET /tâches/métadonnées). En plaçant des points d'accès connexes sous le même parent, la ressource (c.-à-d. /tâches), l'API devient intuitive et l'objectif d'un point d'accès peut (généralement) être déterminé à l'avance. d'un point de terminaison peut (généralement) être déduit de son chemin d'accès et de sa méthode HTTP.

Réflexions complémentaires :

  1. Si chaque donnée n'est utile qu'en combinaison avec d'autres données (pour un tableau de bord statistique, par exemple), vous pouvez éventuellement exposer un seul point de terminaison qui agrège et renvoie tous les comptages en en une seule fois.
  2. Si vous disposez d'un point d'accès pour lister toutes les ressources (c'est-à-dire GET /tasks pour lister toutes les tâches), le décompte pourrait être inclus dans la réponse sous forme de métadonnées, soit dans les en-têtes HTTP, soit dans le corps de la réponse. Ce faisant, l'API sera inutilement sollicitée, ce qui peut être négligeable en fonction de votre cas d'utilisation. négligeable en fonction de votre cas d'utilisation.

0voto

Anon Points 824

En voyant que le préfixe "X-" était obsolète. Voici ce que j'ai trouvé :

  1. Ajout d'un autre élément compte:23 à la réponse
  2. Supprime l'élément de la réponse avant d'utiliser les données dans l'application.

0voto

Paulo Merson Points 611

Si le nombre de ressources est métadonnées des ressources \=> nouveau point de terminaison

Si le nombre de ressources (et éventuellement d'autres métadonnées) est utile à l'application cliente et à l'utilisateur final, il n'est pas nécessaire qu'il figure dans un en-tête ; il peut légitimement se trouver dans le corps de la réponse. Il peut y avoir d'autres métadonnées (d'autres totaux, moyennes ou statistiques en général) qui sont pertinentes pour une ressource donnée.

Dans ce cas, j'utiliserais un point final spécifique pour les métadonnées des ressources. Pour en revenir à l'exemple des membres du réseau social dans la question initiale, il pourrait y en avoir :

GET /api/members         // collection of members, which could be paginated
GET /api/members/{id}    // a single member
GET /api/members/stats   // total member count; member count per region; average posts per member; etc.

Au lieu de stats vous pouvez préférer metadata , totals ou quelque chose d'autre dans le point final (YMMV). Mais nous considérons que ce point d'arrivée renvoie quelque chose de spécifique pour le membres ressources. C'est pourquoi il s'agit d'un point de terminaison distinct et non d'un paramètre de chaîne de requête. De la même manière, nous devrions avoir un point de terminaison distinct - et non un paramètre de requête - pour les messages d'un membre :

GET /api/members/{id}/posts   

Si le nombre de ressources est pour pagination \=> utiliser des en-têtes

Si l'application cliente gère le nombre de ressources renvoyées dans la requête GET à des fins de pagination, ce nombre de ressources est le suivant messagerie métadonnées.

Dans ce cas, je suis d'accord pour dire que l'utilisation d'en-têtes est une meilleure approche. Vous devriez consulter les réponses de Stijn de Witt y adnan kamili .

-1voto

Wooff Points 145

Lorsque vous demandez des données paginées, vous connaissez (par la valeur explicite du paramètre de taille de page ou par la valeur par défaut de la taille de page) la taille de la page, ce qui vous permet de savoir si vous avez reçu toutes les données dans la réponse ou non. Lorsque la réponse contient moins de données que la taille de la page, cela signifie que vous avez obtenu toutes les données. Lorsqu'une page complète est renvoyée, vous devez redemander une autre page.

Je préfère avoir un point de terminaison séparé pour le comptage (ou le même point de terminaison avec le paramètre countOnly). En effet, il est possible de préparer l'utilisateur final à un processus long et fastidieux en affichant une barre de progression correctement initialisée.

Si vous souhaitez renvoyer la taille des données dans chaque réponse, il faut également mentionner la taille de la page et le décalage. Pour être honnête, la meilleure façon est de répéter les filtres de la requête. Mais la réponse devient très complexe. Je préfère donc un point de terminaison dédié pour renvoyer le nombre de données.

<data>
  <originalRequest>
    <filter/>
    <filter/>
  </originalReqeust>
  <totalRecordCount/>
  <pageSize/>
  <offset/>
  <list>
     <item/>
     <item/>
  </list>
</data>

Je préfère un paramètre countOnly au point de terminaison existant. Ainsi, lorsqu'il est spécifié, la réponse ne contient que des métadonnées.

endpoint?filter=value

<data>
  <count/>
  <list>
    <item/>
    ...
  </list>
</data>

endpoint?filter=value&countOnly=true

<data>
  <count/>
  <!-- empty list -->
  <list/>
</data>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X