Implémentation des totaux de pagination et de recherche avec la recherche FHIR

La mise en œuvre de la recherche FHIR de l'API Cloud Healthcare est très évolutive et performante, tout en respectant les consignes et les limites de REST et de la spécification FHIR. Pour ce faire, la recherche FHIR possède les propriétés suivantes:

  • Le total des recherches est une estimation jusqu'à ce que la dernière page soit renvoyée. Les résultats de recherche renvoyés par la méthode fhir.search incluent le total de la recherche (la propriété Bundle.total), qui correspond au nombre total de correspondances dans la recherche. Le total de la recherche est une estimation jusqu'à ce que la dernière page de résultats de recherche soit renvoyée. Le total de la recherche renvoyé avec la dernière page de résultats est une somme précise de toutes les correspondances de la recherche.

  • Les résultats de recherche fournissent une pagination séquentielle. Lorsque davantage de résultats de recherche doivent être affichés, la réponse inclut une URL de pagination (Bundle.link.url) permettant d'obtenir la page de résultats suivante.

Cas d'utilisation de base

La recherche FHIR fournit des solutions aux cas d'utilisation suivants:

Consultez les sections suivantes pour connaître les solutions possibles pour ces cas d'utilisation.

Parcourir l'ordre de navigation

Vous pouvez créer une application à faible latence qui permet à un utilisateur de parcourir les pages de résultats de manière séquentielle jusqu'à ce qu'il trouve la correspondance qu'il souhaite. Cette solution est réalisable si le nombre de correspondances est suffisamment faible pour que l'utilisateur puisse trouver la correspondance souhaitée en parcourant page par page sans ignorer les résultats. Si votre cas d'utilisation nécessite que les utilisateurs puissent avancer de plusieurs pages à la fois ou revenir en arrière, consultez la section Accéder à une page à proximité.

Cette solution ne peut pas fournir un total de recherche précis tant que la dernière page de résultats n'est pas renvoyée. Cependant, il peut fournir un total approximatif de recherches avec chaque page de résultats. Bien qu'un nombre total de recherches précis puisse être requis pour un processus en arrière-plan, un total approximatif de recherches convient généralement à un utilisateur humain.

Workflow

Voici un exemple de workflow pour cette solution:

  1. Une application appelle la méthode fhir.search, qui renvoie la première page de résultats de recherche. La réponse inclut une URL de pagination (Bundle.link.url) si d'autres résultats sont à renvoyer. La réponse inclut également le total de la recherche (Bundle.total). S'il y a plus de résultats à renvoyer que dans la réponse initiale, le total de la recherche n'est qu'une estimation. Pour en savoir plus, consultez la section Pagination et tri.

  2. L'application affiche la page de résultats de recherche, un lien vers la page de résultats suivante (le cas échéant) et le total de la recherche.

  3. Si l'utilisateur souhaite afficher la page de résultats suivante, il clique sur le lien. L'URL de pagination est alors appelée. La réponse inclut une nouvelle URL de pagination si d'autres résultats sont à renvoyer. La réponse inclut également le total de la recherche. Il s'agit d'une estimation mise à jour s'il y a davantage de résultats à renvoyer.

  4. L'application affiche la nouvelle page de résultats de recherche, un lien vers la page de résultats suivante (le cas échéant) et le total de la recherche.

  5. Les deux étapes précédentes sont répétées jusqu'à ce que l'utilisateur arrête la recherche ou que la dernière page de résultats soit renvoyée.

Bonne pratique

Choisissez une taille de page adaptée à un humain sans difficulté. Selon votre cas d'utilisation, cela peut atteindre 10 à 20 correspondances par page. Les pages de petite taille se chargent plus rapidement, et un utilisateur peut avoir des difficultés à gérer un trop grand nombre de liens sur une page. Vous contrôlez la taille de la page avec le paramètre _count.

Traiter un ensemble de résultats de recherche

Vous pouvez obtenir un ensemble de résultats de recherche en effectuant des appels successifs à la méthode fhir.search à l'aide de l'URL de pagination. Si le nombre de résultats de recherche est suffisamment faible, vous pouvez obtenir un ensemble complet de résultats en continuant jusqu'à ce qu'il n'y ait plus de pages à renvoyer. Un total de recherches précis est inclus sur la dernière page de résultats. Une fois les résultats de recherche obtenus, votre application peut les lire et effectuer le traitement, l'analyse ou l'agrégation dont vous avez besoin.

N'oubliez pas que si vous avez un très grand nombre de résultats de recherche, il est possible que vous ne puissiez pas obtenir la dernière page de résultats de recherche (et le total exact de la recherche) en peu de temps.

Workflow

Voici un exemple de workflow pour cette solution:

  1. L'application appelle la méthode fhir.search, qui renvoie la première page de résultats de recherche. La réponse inclut une URL de pagination (Bundle.link.url) si d'autres résultats sont à renvoyer.

  2. Si d'autres résultats doivent être affichés, l'application appelle l'URL de pagination de l'étape précédente pour obtenir la page de résultats de recherche suivante.

  3. L'application répète l'étape précédente jusqu'à ce qu'il n'y ait plus de résultats à renvoyer ou jusqu'à ce qu'une limite prédéfinie soit atteinte. Si vous accédez à la dernière page de résultats de recherche, le total de la recherche est exact.

  4. L'application traite les résultats de recherche.

Selon votre cas d'utilisation, votre application peut effectuer l'une des opérations suivantes:

  • Attendez de recevoir tous les résultats de la recherche avant de traiter les données.
  • Traiter les données à mesure qu'elles sont reçues à chaque appel successif de fhir.search
  • Définissez une limite, telle que le nombre de correspondances renvoyées ou le temps écoulé. Une fois la limite atteinte, vous pouvez traiter les données, mais pas les traiter, ou effectuer une autre action.

Options de conception

Voici quelques options de conception qui peuvent réduire la latence de recherche:

  • Définissez une grande taille de page. Utilisez le paramètre _count pour définir une grande taille de page, pouvant aller de 500 à 1 000, en fonction de votre cas d'utilisation. L'utilisation d'une plus grande taille de page augmente la latence pour chaque extraction de page, mais peut accélérer le processus global, car elle nécessite moins d'explorations pour obtenir l'ensemble des résultats de recherche.

  • Limitez les résultats de recherche. Si vous avez simplement besoin d'un total de recherche précis (vous n'avez pas besoin de renvoyer le contenu de la ressource), définissez le paramètre _elements de la méthode fhir.search sur identifier. Cela peut réduire la latence de votre requête de recherche par rapport à la demande de retour de ressources FHIR complètes. Pour en savoir plus, consultez la section Limiter les champs renvoyés dans les résultats de recherche.

Cas d'utilisation nécessitant un préchargement et une mise en cache

Vous aurez peut-être besoin d'autres fonctionnalités que le simple mécanisme qui consiste à appeler successivement la méthode fhir.search à l'aide d'URL de pagination. Vous pouvez créer une couche de mise en cache entre votre application et le magasin FHIR qui maintient l'état de la session tout en préchargeant et en mettant en cache les résultats de recherche. L'application peut regrouper les résultats de recherche en petites "pages d'application" de 10 ou 20 correspondances. L'application peut ensuite diffuser rapidement ces petites pages d'application auprès de l'utilisateur de manière directe et non séquentielle, en fonction des sélections de l'utilisateur. Pour obtenir un exemple de ce type de workflow, consultez la section Accéder à une page à proximité.

Vous pouvez créer une solution à faible latence qui permet à un utilisateur de parcourir un grand nombre de résultats de recherche jusqu'à ce qu'il trouve la correspondance recherchée. Il peut s'adapter à un nombre pratiquement illimité de correspondances, tout en maintenant une latence faible et en entraînant une augmentation relativement faible de la consommation des ressources. Un utilisateur peut accéder directement à une page de résultats de recherche (jusqu'à un nombre prédéterminé de pages avant ou arrière par rapport à la page actuelle). Vous pouvez fournir une estimation du nombre total de recherches avec chaque page de résultats. Pour référence, cette conception est semblable à celle de la recherche Google.

Workflow

La figure 1 présente un exemple de workflow pour cette solution. Avec ce workflow, chaque fois que l'utilisateur sélectionne une page de résultats à afficher, l'application fournit des liens vers des pages à proximité. Dans ce cas, l'application fournit des liens vers des pages situées jusqu'à cinq vers l'arrière à partir de la page sélectionnée et jusqu'à quatre pages en avant à partir de la page sélectionnée. Pour que les quatre pages suivantes puissent être consultées, l'application précharge 40 correspondances supplémentaires lorsque l'utilisateur sélectionne une page de résultats.

préchargement et mise en cache

Figure 1 : L'application regroupe les résultats de recherche dans des "pages d'application" mises en cache et mises à la disposition de l'utilisateur.

La figure 1 illustre les étapes suivantes:

  1. L'utilisateur saisit une requête de recherche dans l'interface de l'application, ce qui lance les actions suivantes:

    1. L'application appelle la méthode fhir.search pour précharger la première page de résultats de recherche.

      Le paramètre _count est défini sur 100 afin de maintenir la taille de page de la réponse relativement petite, ce qui se traduit par des temps de réponse relativement rapides. La réponse inclut une URL de pagination (Bundle.link.url) si d'autres résultats sont à renvoyer. La réponse inclut également le total de la recherche (Bundle.total). Le total de la recherche est une estimation s'il y a davantage de résultats à renvoyer. Pour en savoir plus, consultez la section Pagination et tri.

    2. L'application envoie la réponse à la couche de mise en cache.

  2. Dans la couche de mise en cache, l'application regroupe les 100 correspondances de la réponse en 10 pages d'application de 10 correspondances chacune. Une page d'application est un petit groupe de correspondances que l'application peut présenter à l'utilisateur.

  3. L'application présente à l'utilisateur la page 1 de l'application. La page 1 de l'application comprend des liens vers les pages 2 à 10 de l'application et une estimation du nombre total de recherches.

  4. L'utilisateur clique sur un lien vers une autre page d'application (page 10 de l'application dans cet exemple), ce qui lance les actions suivantes:

    1. L'application appelle la méthode fhir.search à l'aide de l'URL de pagination renvoyée avec le préchargement précédent pour précharger la page suivante des résultats de recherche.

      Le paramètre _count est défini sur 40 pour précharger les 40 prochaines correspondances à partir de la requête de recherche de l'utilisateur. Les 40 correspondances concernent les quatre pages suivantes de l'application mises à la disposition de l'utilisateur.

    2. L'application envoie la réponse à la couche de mise en cache.

  5. Dans la couche de mise en cache, l'application regroupe les 40 correspondances de la réponse en quatre pages d'application de 10 correspondances chacune.

  6. L'application présente à l'utilisateur la page 10 de l'application. La page 10 de l'application inclut des liens vers les pages 5 à 9 (les cinq pages de l'application en arrière à partir de la page 10 de l'application) et des liens vers les pages 11 à 14 de l'application (les quatre pages à partir de la page 10 de l'application). La page 10 de l'application inclut également le nombre total estimé de recherches.

Ce processus peut se poursuivre tant que l'utilisateur souhaite continuer à cliquer sur des liens vers les pages de l'application. Notez que si l'utilisateur revient en arrière à partir de la page actuelle de l'application et que toutes les pages d'application à proximité sont déjà mises en cache, vous pouvez choisir de ne pas effectuer de nouveau préchargement, en fonction de votre cas d'utilisation.

Cette solution est rapide et efficace pour les raisons suivantes:

  • Les préchargements de petite taille et les pages d'application même de petite taille sont traités rapidement.
  • Les résultats de recherche mis en cache évitent d'avoir à effectuer plusieurs appels pour les mêmes résultats.
  • Le mécanisme reste rapide, quel que soit l'importance de l'échelle des résultats de recherche.

Options de conception

Voici quelques options de conception à envisager, selon votre cas d'utilisation:

  • Taille de la page de l'application. Les pages de votre application peuvent contenir plus de 10 correspondances si cela convient à votre cas d'utilisation. Gardez à l'esprit que les pages de petite taille se chargent plus rapidement et qu'un trop grand nombre de liens sur une page peut être difficile à gérer pour un utilisateur.

  • Nombre de liens vers les pages de l'application. Dans le workflow suggéré ici, chaque page de l'application renvoie neuf liens vers d'autres pages de l'application: cinq liens vers les pages de l'application directement en arrière à partir de la page actuelle de l'application et quatre liens vers les pages directement transférées à partir de la page actuelle de l'application. Vous pouvez ajuster ces valeurs en fonction de votre cas d'utilisation.

Bonnes pratiques

  • N'utilisez la couche de mise en cache que si nécessaire. Si vous configurez une couche de mise en cache, ne l'utilisez que lorsque votre cas d'utilisation l'exige. Les recherches qui ne nécessitent pas la couche de mise en cache doivent l'ignorer.

  • Réduisez la taille de votre cache. Pour économiser les ressources, vous pouvez réduire la taille de votre cache en supprimant définitivement vos anciens résultats de recherche tout en conservant les URL des pages que vous avez utilisées pour obtenir ces résultats. Vous pouvez ensuite reconstruire le cache si nécessaire en appelant les URL des pages. N'oubliez pas que les résultats de plusieurs appels à la même URL de pagination peuvent changer au fil du temps, car les ressources du magasin FHIR sont créées, mises à jour et supprimées en arrière-plan. Les décisions de conception qui dépendent de votre cas d'utilisation dépendent de la suppression, de la méthode de suppression définitive et de la fréquence de suppression définitive du cache.

  • Videz le cache pour une recherche donnée. Pour conserver les ressources, vous pouvez supprimer complètement du cache les résultats des recherches inactives. Commencez par supprimer les recherches inactives les plus longues. Gardez à l'esprit que si une recherche supprimée définitivement redevient active, cela peut entraîner un état d'erreur qui oblige la couche de mise en cache à redémarrer la recherche.

Si vous souhaitez qu'un utilisateur puisse accéder à n'importe quelle page des résultats de recherche, et pas seulement à celles situées à proximité de la page actuelle, vous pouvez utiliser une couche de mise en cache semblable à celle décrite dans la section Accéder à une page à proximité. Toutefois, pour permettre à un utilisateur d'accéder à n'importe quelle page de résultats de recherche d'une application, vous devez précharger et mettre en cache tous les résultats de recherche. Avec un nombre relativement faible de résultats de recherche, c'est possible. Avec un très grand nombre de résultats de recherche, il peut être impossible, voire impossible, de tous les précharger. Même avec un nombre réduit de résultats de recherche, le temps nécessaire au préchargement peut être plus long qu'il est raisonnable d'attendre un utilisateur.

Workflow

Configurez un workflow semblable à Navigate to a nearby page (Accéder à une page à proximité), à cette différence clé: l'application continue à précharger les résultats de recherche en arrière-plan jusqu'à ce que toutes les correspondances soient renvoyées ou jusqu'à ce qu'une autre limite prédéfinie soit atteinte.

Voici un exemple de workflow pour cette solution:

  1. L'application appelle la méthode fhir.search pour précharger la première page de résultats de recherche à partir de la requête de recherche de l'utilisateur. La réponse inclut une URL de pagination (Bundle.link.url) si d'autres résultats sont à renvoyer. La réponse inclut également le total de la recherche (Bundle.total). Il s'agit d'une estimation s'il y a davantage de résultats à renvoyer.

  2. L'application regroupe les correspondances de la réponse dans des pages de 20 correspondances et les stocke dans le cache. Une page d'application est un petit groupe de correspondances que l'application peut présenter à l'utilisateur.

  3. L'application affiche la première page de l'application à l'utilisateur. La page de l'application comprend des liens vers les pages de l'application mises en cache et une estimation du nombre total de recherches.

  4. Si d'autres résultats doivent être affichés, l'application effectue les opérations suivantes:

    • Appelle l'URL de pagination renvoyée par le préchargement précédent pour obtenir la page de résultats de recherche suivante.
    • Regroupe les correspondances de la réponse dans des pages d'application de 20 correspondances et les stocke dans le cache.
    • Actualise la page de l'application actuellement consultée par l'utilisateur avec de nouveaux liens vers les pages d'application nouvellement préchargées et mises en cache.
  5. L'application répète l'étape précédente jusqu'à ce qu'il n'y ait plus de résultats à renvoyer ou jusqu'à ce qu'une limite prédéfinie soit atteinte. Un total précis est renvoyé avec la dernière page de résultats de recherche.

Pendant que l'application précharge et met en cache les correspondances en arrière-plan, l'utilisateur peut continuer à cliquer sur des liens vers des pages mises en cache.

Options de conception

Voici quelques options de conception à envisager, selon votre cas d'utilisation:

  • Taille de la page de l'application. Les pages de votre application peuvent contenir plus ou moins de 20 correspondances si cela convient à votre cas d'utilisation. Gardez à l'esprit que les pages de petite taille se chargent plus rapidement et qu'un trop grand nombre de liens sur une page peut être difficile à gérer pour un utilisateur.

  • Actualisez le total des recherches. Pendant que votre application précharge et met en cache les résultats de recherche en arrière-plan, vous pouvez présenter progressivement à l'utilisateur des totaux de recherche plus précis. Pour ce faire, configurez votre application comme suit:

    • À un intervalle défini, récupérez le total de la recherche (la propriété Bundle.total) à partir du dernier préchargement dans la couche de mise en cache. Il s'agit de la meilleure estimation actuelle du total de la recherche. Afficher le total des recherches pour indiquer à l'utilisateur qu'il s'agit d'une estimation. Déterminez la fréquence de cette actualisation en fonction de votre cas d'utilisation.

    • Identifier à quel moment le total de la recherche provenant de la couche de mise en cache est précis. Autrement dit, le total de la recherche provient de la dernière page de résultats de recherche. Lorsque la dernière page de résultats de recherche est atteinte, l'application affiche le total de la recherche et indique à l'utilisateur que ce total est exact. L'application cesse alors d'obtenir les totaux de recherche de la couche de mise en cache.

    Notez qu'avec un grand nombre de correspondances, la préchargement en arrière-plan et la mise en cache peuvent ne pas atteindre la dernière page des résultats de recherche (et le total de la recherche exacte) avant que l'utilisateur n'ait terminé sa session de recherche.

Bonnes pratiques

  • Dédupliquez les ressources incluses. Si vous utilisez les paramètres _include et _revinclude lors du préchargement et de la mise en cache des résultats de recherche, nous vous recommandons de dédupliquer les ressources incluses dans le cache après chaque préchargement. Cela permet d'économiser de la mémoire en réduisant la taille de votre cache. Lorsque vous regroupez des correspondances dans des pages d'application, ajoutez les ressources incluses appropriées à chaque page d'application. Pour en savoir plus, consultez la section Inclure des ressources supplémentaires dans les résultats de recherche.

  • Définissez une limite pour la prélecture et la mise en cache. Avec un très grand nombre de résultats de recherche, il peut être impossible, voire impossible, de tous les précharger. Nous vous recommandons de limiter le nombre de résultats de recherche à précharger. Cela permet de conserver une taille de cache gérable et d'économiser de la mémoire. Par exemple, vous pouvez limiter la taille de votre cache à 10 000 ou à 20 000 correspondances. Vous pouvez également limiter le nombre de pages à précharger ou définir une limite de temps après laquelle le préchargement s'arrêtera. Le type de limite que vous fixez et la manière dont vous l'imposez sont des décisions de conception qui dépendent de votre cas d'utilisation. Si la limite est atteinte avant que tous les résultats de recherche ne soient renvoyés, pensez à en informer l'utilisateur, en indiquant que le nombre total de recherches est encore une estimation.

Mise en cache de l'interface

L'interface de l'application, telle qu'un navigateur Web ou une application mobile, peut fournir une mise en cache des résultats de recherche au lieu d'introduire une couche de mise en cache dans l'architecture. Cette approche permet de naviguer vers la page précédente ou vers n'importe quelle page de l'historique de navigation en exploitant les appels AJAX et en stockant les résultats de recherche et/ou les URL de pagination. Voici quelques avantages de cette approche:

  • Elle peut nécessiter moins de ressources qu'une couche de mise en cache.
  • Il est plus évolutif, car il répartit le travail de mise en cache entre de nombreux clients.
  • Il est plus facile de déterminer à quel moment les ressources mises en cache ne sont plus nécessaires, par exemple lorsque l'utilisateur ferme un onglet ou quitte l'interface de recherche.

Bonnes pratiques générales

Voici quelques bonnes pratiques qui s'appliquent à toutes les solutions de ce document.

  • Prévoyez des pages dont la taille est inférieure à la valeur "_count". Dans certains cas, une recherche peut renvoyer des pages contenant moins de correspondances que la valeur _count que vous spécifiez. Cela peut se produire, par exemple, si vous spécifiez une taille de page particulièrement importante. Si votre recherche renvoie une page inférieure à la valeur _count et que votre application utilise une couche de mise en cache, vous devrez peut-être (1) afficher moins de résultats que prévu sur la page d'une application ou (2) extraire quelques résultats supplémentaires pour en obtenir suffisamment pour obtenir une page d'application complète. Pour en savoir plus, consultez la section Pagination et tri.

  • Relancez les erreurs de requêtes HTTP récupérables. Votre application doit s'attendre à des erreurs de requête HTTP récupérables, telles que 429 ou 500, et effectuer de nouvelles tentatives après les avoir reçues.

Évaluer vos cas d'utilisation

La mise en œuvre de fonctionnalités telles que la navigation vers n'importe quelle page, l'obtention de totaux de recherche précis et la mise à jour des totaux estimés augmentent la complexité et les coûts de développement de votre application. Ces fonctionnalités peuvent également augmenter la latence et les coûts d'utilisation des ressources Google Cloud. Nous vous recommandons d'évaluer attentivement vos cas d'utilisation pour vous assurer que la valeur de ces fonctionnalités justifie les coûts. Voici quelques éléments à prendre en compte:

  • Accéder à n'importe quelle page : Un utilisateur n'a généralement pas besoin d'accéder à une page spécifique ou à de nombreuses pages de la page actuelle. Dans la plupart des cas, l'option Accéder à une page à proximité est appropriée.

  • Nombre total de recherches précises. Les totaux des recherches peuvent changer à mesure que des ressources sont créées, mises à jour et supprimées dans le magasin FHIR. Pour cette raison, le total exact des recherches est correct au moment où il apparaît (avec la dernière page de résultats de recherche), mais il peut ne pas le rester au fil du temps. Par conséquent, en fonction de votre cas d'utilisation, des totaux de recherches précis peuvent avoir une valeur limitée pour votre application.