Faire un ET sur plusieurs champs commençant par


(Thibaut Tropardy) #1

Je cherche à faire une recherche sur plusieurs champs de type commençant par (en java)
Si l'utilisateur fait un espace, je veux faire un ou.
J'ai fait plusieurs essai de requêtes, et je ne comprend pas toujours la logique

Voici un premier code qui marche

{
"query": {
"filtered": {
"query": {
"query_string": {
"fields": [
"serial",
"produit"
],
"query": "sn15* AND produit1*"
}
}
}
}
}

C'est la requête la plus simple à priori, mais je dois modifier la saisie utilisateur et ajouter le AND à la place du espace.

Cette fonction est-elle la plus optimisé et la plus performante?

Au passage, existe-t-il dans l'api java elasticsearch une fonction utilitaire qui échappe la saisie utilisateur pour éviter qu'il puisse directement saisir les * ? et opérateur, ou doit-je la faire à la main?

Première requête avec l'api JAva

Par contre, avec l'api Java, j'était parti au départ sur AndFilterBuilder et un multiMatchQuery et je n'ai pas le même résultat, sans que je comprenne pourquoi et j'aime comprendre

Voila le code généré par l'api Java

{
"query" : {
"filtered" : {
"query" : {
"match_all" : { }
},
"filter" : {
"and" : {
"filters" : [ {
"query" : {
"multi_match" : {
"query" : "sn15",
"fields" : [ "serial", "produit" ],
"type" : "phrase_prefix"
}
}
}, {
"query" : {
"multi_match" : {
"query" : "produit1",
"fields" : [ "serial","produit" ],
"type" : "phrase_prefix"
}
}
} ]
}
}
}
}
}

bien que plus complexe, cette requête devrait me retourner théoriquement la même chose non? Elle ne me retourne que 11 résultats (contre 318 pour l'autres).
Le plus étonnant, c'est que plus si je met juste "sn" à la place de "sn15", j'ai moins de résultats.

Seriez-vous m'expliquer pourquoi?


(David Pilato) #2

Dans l'idéal, j'utiliserais des edge n gram au niveau analyseur au moment de l'indexation pour faire ça.
Puis un simple analyzer au moment de la recherche.

Du coup une recherche "sn15 AND produit1" devrait fonctionner à mon avis.


(Thibaut Tropardy) #3

Si j'adopte le edge n gram, il faudrait que je duplique le champ, car je ne fait pas que des recherches commence par sur cet objet.
Par contre, le edge n gram, de ce que j'ai compris, il faut a peu près toujours le même nombre de lettre pour la recherche.
Dans mon cas, l'utilisateur peux saisir 2, 4, 6 ou toutes les lettres. le edge gram est-il toujours adapté dans ce cas?

Je pense utiliser la query avec le AND.

Par contre, j'aimerais quand même savoir pourquoi la requête généré par l'api Java n'a pas fonctionné?

Voila mon code

	AndFilterBuilder afb = new AndFilterBuilder();
	for (final String term : letter.split("\\s+")) {
//Pour chaque espace
		afb.add(FilterBuilders.queryFilter(QueryBuilders.multiMatchQuery(StringUtils.lowerCase(term), "serial", "produit")
				.type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX)));
	}
	searchRequestBuilderResult.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), afb));

Pour essayer, j'ai testé avec un AND sur 2 QueryBuilders.prefixQuery chaqun associé au bon champ et ca a marché.

C'est donc le multiMatchQuery qui fait que le ANd ne marche pas,


(David Pilato) #4

Tu peux utiliser le multifield ("fields") qui évite de dupliquer mais permet d'indexer le même champ de différentes façon.

Le edgengram génère des sous tokens à partir d'un token.

Abcdef sera indexé par exemple en abc, abcd, abcde et abcdef.

Si ton utilisateur cherche abcd, ça matchera parfaitement.


(system) #5