Utiliser la recherche textuelle

Utilisez les fonctionnalités de recherche textuelle dans Cloud Firestore pour rechercher des chaînes spécifiques dans une collection.

Avant de commencer

Avant de commencer à utiliser les requêtes textuelles, procédez comme suit :

  1. Assurez-vous d'avoir accès à une base de données d'opérations compatible avec MongoDB existante ou créez-en une et connectez-vous à celle-ci.

  2. Assurez-vous d'avoir un index textuel ou créez-en un.

Autorisations IAM

Pour créer un index dans Cloud Firestore, assurez-vous que l'un des rôles suivants vous est attribué :

  • roles/datastore.owner
  • roles/datastore.indexAdmin
  • roles/editor
  • roles/owner

Pour attribuer un rôle, consultez la section Attribuer un rôle unique. Pour en savoir plus sur les rôles Cloud Firestore et les autorisations associées, consultez la section Rôles prédéfinis.

Si vous avez défini des rôles personnalisés, attribuez toutes les autorisations suivantes pour créer des index :

  • datastore.indexes.create
  • datastore.indexes.delete
  • datastore.indexes.get
  • datastore.indexes.list
  • datastore.indexes.update

Exécuter une requête textuelle

Les requêtes textuelles utilisent l'opérateur $text dans un filtre. Spécifiez la chaîne interrogée dans l'argument $search.

Exécuter une requête textuelle générale

Exécutez la requête suivante pour effectuer une requête générale :

  # Find query
  db.cities.find({ $text: { $search: "french bread" } })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "french bread" } } }
  ]);

Si votre index est partitionné, vous pouvez filtrer en fonction de la partition en l'incluant dans un filtre d'égalité "and" dans votre requête. Par exemple, si vous aviez une partition city, vous pouvez filtrer une requête textuelle comme suit :

db.myCollection.find( { $and: [
  { $text: { $search: "french bread" } },
  { "city": "Paris" }
] } )

Vous pouvez également filtrer une agrégation en fonction d'une partition. Exemple :

db.myCollection.aggregate([
 { $match: { $text: { $search: "french bread" } } },
 { "city": "Paris" }
] );

La valeur de votre partition doit être une chaîne. Votre filtre de partition doit être joint à votre requête à l'aide d'un "and".

Définir la langue de la requête

Vous pouvez définir la langue de la requête à l'aide de l'argument $language. Exemple :

  db.cities.find({ $text: { $search: "french bread", $language: "en"} })

Si vous ne définissez pas la langue de la requête, celle-ci utilise la langue de l'index textuel.

Interroger un terme exact

Pour interroger un terme exact, configurez-le comme une séquence de mots entre guillemets doubles. Exemple :

  # Find query
  db.cities.find({ $text: { $search: "\"best french bread\"" } })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "\"best french bread\"" } } },
  ]);

Interroger une combinaison de termes

Pour rendre votre requête plus précise, spécifiez une chaîne de termes. Par exemple, la requête suivante renvoie les documents qui correspondent à la combinaison best AND french AND ("bread" OR "is") :

  # Find query
  db.cities.find({ $text: { $search: "\"best\" \"french\" bread is" } })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "\"best\" \"french\" bread is" } } },
  ]);

Exclure un terme

Pour exclure un terme d'une requête, ajoutez un préfixe avec un trait d'union (-) :

  # Find query
  db.cities.find({ $text: { $search: "best bread -french"} })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "best bread -french" } } },
  ]);

Calculer le score de pertinence

Utilisez l'expression {$meta: "textScore"} pour calculer le score de pertinence des documents correspondant à la requête textuelle. Pour trier les résultats par ordre décroissant, utilisez $meta dans une expression de tri. Prenons les exemples suivants, où SCORE_FIELD est le nom du champ utilisé pour stocker la valeur du score :

  # Find query
  db.cities
    .find({ $text: { $search: "best french bread" } })
    .sort({ SCORE_FIELD: { $meta: "textScore" } })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "best french bread" } } },
    { $sort: { "SCORE_FIELD": { $meta: "textScore"} } },
  ]);

Vous pouvez également utiliser le score de texte dans les expressions de projection. Exemple :

  # Find query
  db.cities
    .find({ $text: { $search: "best french bread" } })
    .project({ score: { $meta: "textScore" } })

  # Aggregation query
  db.cities.aggregate([
    { $match: { $text: { $search: "best french bread" } } },
    { $project: { "scoreField": { $meta: "textScore"} } },
  ]);

Développer la requête

Pour améliorer la pertinence des résultats de la requête, l'opérateur $text augmente la chaîne de recherche en fonction de la langue spécifiée afin d'inclure les correspondances pour les synonymes contextuels, les formes dérivées, les termes corrigés orthographiquement, les variantes diacritiques, etc.

Limites

  • Les opérateurs $near et $text ne peuvent pas être utilisés dans la même requête.
  • Un seul opérateur $text est autorisé par requête find ou aggregation.
  • Dans les agrégations, l'étape $match avec $text doit être la première étape du pipeline.
  • $text ne peut être imbriqué que dans $and et $or.
  • Si $text se trouve dans $or, les disjonctions non liées à la recherche peuvent utiliser des index ordonnés existants pour optimiser la requête. Si les autres disjonctions ne sont pas indexées, la requête s'appuiera sur une analyse de la collection.
  • $text ne peut pas être utilisé avec des indications de requête.
  • Les requêtes avec recherche textuelle ne peuvent pas être triées par $natural.