Lors de l’élaboration d’une query Elasticsearch permettant de rechercher et de récupérer des données au sein d’un index, le nombre de possibilités peuvent aisément amener à poser des questions. Parfois même, il est difficile de réellement voir la différence entre un choix et un autre. C’est notamment le cas des deux mots-clés que sont must et filter. En apparence très similaire, il est en fait intéressant de comprendre la légère subtilité qui réside entre ces deux options. Une bonne connaissance de cette différence permettra alors un choix plus avisé de l’un ou l’autre des mots-clés.
Au premier abord, une même requête de recherche sur un même index Elasticsearch avec le mot-clé must et le mot-clé filter semble identique. Afin d’illustrer le propos de cet article, j’ai défini un cas d’exemple d’un index composé de plus de 2 millions de documents.
Ci-dessous, vous pouvez apercevoir deux requêtes différentes sur notre index d’exemple. L’une utilise le mot-clé filter, l’autre le mot-clé must. Mais chacune d’entre elle cherche à récupérer seulement les documents de l’index qui disposent d’un champ code à la racine.
{
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "code"
}
}
]
}
}
}
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "code"
}
}
]
}
}
}
hits": {
"total": {
"value": 194026,
"relation": "eq"
},
...
Le résultat retourné en réponse à la requête montre qu’elles retournent toutes deux le même nombre de documents. Mais alors, quelle est la véritable différence entre les deux mots-clés si leur logique semble aussi similaire ?
Elasticsearch dispose en interne d’une capacité à calculer des score de pertinence pour chacun des documents retournés en réponse de la requête de recherche. Par ce biais, il peut alors classifier les résultats d’une recherche en fonction du score de pertinence calculé pour chacun des documents ayant été retourné.
Et c’est bien là que réside la subtile différence entre les deux mot-clés que sont must et filter. En effet, tandis que filter ne dispose d’aucun calcul de score sous-jacent lors de la requête de recherche, ce calcul de score est lui inhérent au mot-clé must. L’insérer dans la requête de recherche au sein de l’index, c’est comprendre que l’on souhaite avoir également dans la réponse un calcul de pertinence pour chacun des documents retournés.
On peut d’ailleurs voir la différence dans la réponse des requêtes utilisant chacune l’un des deux mots-clés.
Filter : "max_score": 0.0
Must : "max_score": 1.0
Nous sommes ici dans un cas d’exemple de recherche très basique qui créer des résultats de pertinence uniforme pour le mot-clé must où chacun des documents retourné dispose du champ code. Le mot-clé filter, lui, renvoi aussi un score en réponse mais défini par défaut à 0, montrant justement qu’aucun calcul de score n’a été effectué.
Et si nous faisons un test de performance entre les deux mots-clés sur un index disposant de seulement quelques dizaines voire même quelques centaines de documents, il se peut que nous trouvions alors la différence d’exécution de la requête insignifiante et donc clairement non-significative. Néanmoins, si nous prenons le cas de notre exemple, un index avec plusieurs millions de documents, le résultat de temps d’exécution de la requête pour chacun des mots-clés est le suivant :
Filter : 30 ms
Must : 425 ms
Dans le contexte de notre exemple, la requête à l’aide du mot-clé filter peut alors s’exécuter près de 14 fois plus rapidement que la même requête, dans le même environnement, renvoyant les mêmes résultats, mais avec l’utilisation du mot-clé must qui engendre le calcul des scores de pertinence pour chacun des documents répondant aux critères de la recherche.
Ainsi, il est important de bien saisir le besoin de son application, le contexte dans lequel la recherche est effectuée. L’utilisation du mot-clé must implique un travail supplémentaire durant la requête de recherche. Dans un cadre de projet de petite ampleur, le choix de l’un ou l’autre des mots-clés n’impliquera que peu de différence. Mais ce choix pourra s’avérer bien plus coûteux pour les performances de recherche de l’application sur des projets de plus grande ampleur, associé à des indices Elasticsearch d’une tout autre taille.
Pour éviter ces écueils imprévus alors que le projet gagne en ampleur par exemple, n’utilisez le mot-clé must que lorsque votre application nécessite réellement une classification des documents retournés lors de la requête de recherche. Ces scénarios où les utilisateurs disposent d’un réel besoin de classification des résultats de leurs recherches par pertinence. Ceux où cette fonctionnalité leur apporte une réelle plus value.
Dans tous les autre cas, le mot-clé filter sera suffisant, et même la meilleure option.