Présentation d'une requête avec filtres de plage et d'inégalité sur plusieurs propriétés

Firestore en mode Datastore permet d'utiliser des filtres de plage et d'inégalité sur plusieurs propriétés dans une seule requête. Cette fonctionnalité vous donne des conditions de plage et d'inégalité sur plusieurs propriétés et simplifie le développement de votre application en déléguant l'implémentation du post-filtrage vers Firestore en mode Datastore.

Filtres de plage et d'inégalité sur plusieurs propriétés

La requête suivante utilise des filtres de plage sur la priorité et les jours pour renvoyer toutes les tâches dont la priorité est supérieure à quatre et qui doivent être terminées en moins de trois jours.

Go

query := datastore.NewQuery("Task").
   FilterField("priority", ">", 4).
   FilterField("days", "<", 3).

GQL

SELECT * FROM /tasks WHERE priority > 4 AND days < 3;

Java

Query<Entity> query =
    Query.newEntityQueryBuilder()
      .setKind("Task")
      .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("priority", 4), PropertyFilter.lt("days", 3)))
    .build();

Node.js

const query = datastore
  .createQuery('Task')
  .filter(
    and([
      new PropertyFilter('priority', '>', 4),
      new PropertyFilter('days', '<', 3),
    ])
  );

Python

from google.cloud import datastore
client = datastore.Client()
query = client.query(kind="Task")
query.add_filter(filter=PropertyFilter("priority", ">", 4))
query.add_filter(filter=PropertyFilter("days", "<", 3))

PHP

$query = $datastore->query()
    ->kind('Task')
    ->filter('priority', '>', 4)
    ->filter('days', '<', 3)

C#

Query query = new Query("Task")
{
  Filter = Filter.And(Filter.GreaterThan("priority", 4),
    Filter.LessThan("days", 3))
};

Ruby

query = datastore.query("Task")
                 .where("priority", ">", 4)
                 .where("days", "<", 3)

Considérations concernant l'indexation

Avant de commencer à exécuter des requêtes, assurez-vous d'avoir lu sur les requêtes.

Si aucune clause ORDER BY n'est spécifiée, Firestore en mode Datastore utilise un index qui peuvent satisfaire à la condition de filtre de la requête pour la traiter. Cette approche produit un ensemble de résultats ordonnés selon la définition de l'index.

Pour optimiser les performances et les coûts des requêtes Firestore en mode Datastore, optimiser l'ordre des propriétés dans l'index. Pour ce faire, assurez-vous que est ordonné de gauche à droite, de sorte que la requête aboutisse qui empêche l'analyse des entrées d'index superflues.

Par exemple, supposons que vous souhaitiez rechercher dans une collection d'employés ceux dont le salaire est supérieur à 100 000 $ et dont le nombre d'années d'expérience est supérieur à 0. D'après votre compréhension du jeu de données, vous savez que la contrainte de salaire est plus sélective que la contrainte d'expérience. L'index (salary [...], experience [...]) est un index qui réduit le nombre d'analyses d'index. Par conséquent, une requête rapide et économique classe salary avant experience, comme illustré dans l'exemple suivant :

GQL

SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY salary, experience

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
    .setOrderBy(OrderBy("salary"), OrderBy("experience"))
    .build();

Node.js

const query = datastore
  .createQuery("employees")
  .filter(
    and([
      new PropertyFilter("salary", ">", 100000),
      new PropertyFilter("experience", ">", 0),
       ])
    )
  .order("salary")
  .order("experience");

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.add_filter("experience", ">", 0)
query.order = ["-salary", "-experience"]

Bonnes pratiques pour l'optimisation des index

Lorsque vous optimisez des index, tenez compte des bonnes pratiques suivantes.

Classer les requêtes par égalités suivies de la plage la plus sélective ou du champ d'inégalité

Firestore en mode Datastore utilise les propriétés les plus à gauche d'un index composite pour satisfaire les contraintes d'égalité ainsi que la contrainte de plage et d'inégalité, le cas échéant, sur le premier champ de la requête orderBy(). Ces contraintes peuvent réduire le nombre les entrées d'index analysées par Firestore en mode Datastore. Firestore en mode Datastore utilise les propriétés restantes de l'index pour répondre aux autres contraintes de plage et d'inégalité de la requête. Ces contraintes ne réduisent pas le nombre d'entrées d'index Firestore en mode Datastore analyse, mais filtre les entités sans correspondance afin que le nombre le nombre d'entités renvoyées aux clients est réduit.

Pour en savoir plus sur la création d'index efficaces, consultez les sections Structure et définition des index et Optimiser les index.

Classer les propriétés par ordre décroissant de sélectivité de la contrainte de requête

Pour vous assurer que Firestore en mode Datastore sélectionne l'index optimal pour votre requête, spécifier une clause orderBy() qui ordonne les propriétés de plage et d'inégalité en fonction sur le degré de sélectivité de leurs contraintes dans votre requête, en commençant par les de façon sélective. Une sélectivité plus élevée correspond à moins d'entités, tandis qu'une sélectivité plus faible correspond à plus d'entités. Dans l'ordre d'indexation, placez les propriétés de plage et d'inégalité ayant une sélectivité plus élevée avant celles ayant une sélectivité plus faible.

Pour réduire le nombre d'entités que Firestore en mode Datastore analyse et renvoie sur le réseau, vous devez toujours trier les propriétés par ordre décroissant de sélectivité des contraintes de requête. Si l'ensemble de résultats n'est pas dans l'ordre requis et si l'ensemble de résultats attendu est limité, vous pouvez implémenter une logique côté client pour commander à nouveau selon vos attentes.

Par exemple, si vous souhaitez rechercher dans une collection d'employés les employés basés aux États-Unis dont le salaire est supérieur à 100 000 $ et classer les résultats par année d'expérience de l'employé. Si vous prévoyez que seul un petit nombre d'employés auront un salaire supérieur à 100 000 $, voici un moyen efficace d'écrire la requête :

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(PropertyFilter.gt("salary", 100000))
    .setOrderBy(OrderBy("salary"))
    .build();
QueryResults<Entity> results = datastore.run(query);
// Order results by `experience`

Node.js

const query = datastore
  .createQuery("employees")
  .filter(new PropertyFilter("salary", ">", 100000))
  .order("salary");
const [entities] = await datastore.runQuery(query);
// Order results by `experience`

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.order = ["salary"]
results = query.fetch()
// Order results by `experience`

Alors que l'ajout d'un tri sur experience à la requête permet d'obtenir le même ensemble et éviter de réorganiser les résultats sur les clients, la requête peut lire beaucoup plus d'entrées d'index superflues que la requête précédente. En effet, Firestore en mode Datastore préfère toujours un indice dont le préfixe de propriétés d'index correspond à la clause de tri de la requête. Si vous avez ajouté experience à la clause order by : Firestore en mode Datastore sélectionne alors l'index (experience [...], salary [...]) pour calculer les résultats d'une requête. Puisqu'il n'y a pas d'autres contraintes experience, Firestore en mode Datastore lira toutes les entrées d'index de la employees avant d'appliquer le filtre salary pour trouver le résultat final ensemble de résultats. Cela signifie que les entrées d'index qui ne répondent pas aux critères salary sont tout de même lues, ce qui augmente la latence et le coût de la requête.

Tarifs

Les requêtes avec des filtres de plage et d'inégalité sur plusieurs propriétés sont facturées en fonction des entités lues et des entrées d'index lues.

Pour en savoir plus, consultez la page Tarifs.

Limites

En plus des limites des requêtes, veuillez noter les limites suivantes avant d'utiliser des requêtes avec des filtres de plage et d'inégalité sur plusieurs propriétés :

  • Pour éviter que les requêtes ne deviennent trop coûteuses à exécuter, Firestore en mode Datastore limite le nombre d'opérateurs de plage ou d'inégalité à 10.

Étape suivante