[Recherche élastique x Java] Le résultat de l'exécution de la requête acquise en Java étant différent de l'hypothèse, j'ai étudié → Résumé du contenu correspondant

Lorsque j'ai cherché à l'aide d'Elasticsearch en Java, le résultat attendu n'a pas été obtenu, j'ai donc enquêté → répondu. Je vais résumer le contenu.

environnement

Enquête

La source

--Définition d'index

Dans la définition d'index, en plus de la définition des mappages, l'analyseur est également défini comme suit. Le positionnement du nom de champ est le suivant.

Nom de domaine Type de données positionnement
itemId integer ID produit (correspond à la clé primaire)
itemName text Nom du produit
itemNameKana text Nom du produit (Katakana)
itemNameHira text Nom du produit (Hiragana)

Définition d'index


{
  "settings": {
    "analysis": {
      "filter": {
        "my_ngram": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 2
        }
      },
      "analyzer": {
        "my_kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer",
          "char_filter": [
            "icu_normalizer",
            "kuromoji_iteration_mark"
          ],
          "filter": [
            "kuromoji_stemmer",
            "my_ngram"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "itemId": {
        "type": "integer"
      },
      "itemName": {
        "type": "text",
        "analyzer": "my_kuromoji_analyzer"
      },
      "itemNameKana": {
        "type": "text",
        "analyzer": "my_kuromoji_analyzer"
      },
      "itemNameHira": {
        "type": "text",
        "analyzer": "my_kuromoji_analyzer"
      }
    }
  }
}

En tant que processus du côté Java, le mot de recherche saisi est recherché pour toute correspondance dans les champs nom de produit, nom de produit (katakana) ou nom de produit (hiragana), et trié par ordre décroissant de score. C'est le contenu.

Code source Java


	/**
	 *Recherche de produit
	 *
	 * @mot de recherche par mot-clé param
	 * @nom d'index d'index de paramètre
	 * @nombre limite de paramètre
	 * @client param client de connexion Elasticsearch
	 * @renvoyer les résultats de la recherche
	 * @throws IOException
	 */
	public SearchResponse search(String keyword, String index, int limit, RestHighLevelClient client) throws IOException{

		//Initialiser les conditions de recherche
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

		BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

		boolQueryBuilder.should(QueryBuilders.matchQuery("itemName", keyword))
						.should(QueryBuilders.matchQuery("itemNameKana", keyword))
						.should(QueryBuilders.matchQuery("itemNameHira", keyword));

		searchSourceBuilder.query(boolQueryBuilder);
		//Réglage de l'ordre de tri (trier par score)
		searchSourceBuilder.sort(new FieldSortBuilder("_score").order(SortOrder.DESC));
		//Définissez le nombre de retours
		searchBuilder.size(limit);

		SearchRequest request = new SearchRequest(index).source(searchSourceBuilder);

		return client.search(request, RequestOptions.DEFAULT);


	}

Enfin, la requête d'exécution dans Kibana. Entrez le mot que vous souhaitez rechercher à l'endroit où «Rechercher le mot» est entré et recherchez. Spécifiez également 5 pour la taille (limite dans le code source Java).

Requête d'exécution dans Kibana


POST item_list/_search
{
  "from": 0,
  "size": 5,
  "sort": {
    "_score": {
      "order": "desc"
    }
  },
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "itemName": "Entrez un mot de recherche"
           }
        },
        {
          "match": {
            "itemNameKana": "Entrez un mot de recherche"
          }
        },
        {
          "match": {
            "itemNameHira": "Entrez un mot de recherche"
          }
        }
      ]
    }
  }
}

Facteurs candidats

Les éléments suivants sont considérés comme des facteurs candidats.

―― 1. Le contenu de la requête émise en Java est incorrect. ―― 2. Les paramètres de l'analyseur sont incorrects.

J'ai décidé d'enquêter sur ces derniers dans l'ordre.

Mise en œuvre de l'enquête

1. Le contenu de la requête émise en Java est incorrect

Premièrement, du point de vue de savoir si le contenu de la requête émise en Java est incorrect. Comme méthode de confirmation, le code source Java SearchRequest request = new SearchRequest(index).source(searchBuilder); Vous pouvez voir le contenu de searchSourceBuilder en définissant un point d'arrêt dans la phrase à effectuer.

Le contenu était le suivant.

Contenu de searchBuilder


{"size"5,"query":{"bool":{"should":[{"match":{"itemName":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameKana":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameHira":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"sort":[{"_score":{"order":"desc"}}]}

À première vue, il ne semble y avoir aucun problème. Lancer ce contenu dans Kibana a donné exactement le même résultat que de cliquer sur "Exécuter la requête dans Kibana". La requête exécutée est la suivante.

Requête exécutée avec le contenu de searchSourceBuilder


POST item_list/_search
{"size"5,"query":{"bool":{"should":[{"match":{"itemName":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameKana":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameHira":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"sort":[{"_score":{"order":"desc"}}]}

De ce résultat, on peut dire que "le contenu de la requête émise en Java est incorrect" n'est pas la cause. Aussi, lorsque j'ai vérifié le score (_score) à ce stade pour le résultat de l'acquisition en Java (résultat retourné à Elasticsearch → Java: valeur de retour de client.search (request, RequestOptions.DEFAULT)), Kibana Il s'est avéré que c'était différent du résultat de l'exécution. </ b> (C'est un point important qui a été révélé dans l'enquête, je vais donc le mettre en gras)

2. Les paramètres de l'analyseur sont incorrects

Ensuite, du point de vue de savoir si les paramètres de l'analyseur sont incorrects, si les paramètres de l'analyseur sont incorrects, vous devriez obtenir des résultats étranges lorsque vous exécutez une requête dans Kibana. Cette fois, ce n'était pas le cas, donc je savais que «les paramètres de l'analyseur étaient erronés» n'était pas non plus la cause.

3. Il est nécessaire de corriger le contenu implicitement défini.

C'est le reste. Comme il n'y a pas eu de problème avec le contenu de searchSourceBuilder, il est fort possible que

  • request(SearchRequest)
  • client.search(request, RequestOptions.DEFAULT)(SearchResponse)

N'importe quel.

Lorsque j'ai vérifié le contenu de la requête (SearchRequest) en mode débogage,

Contenu de la requête (SearchRequest)


SearchRequest{searchType=QUERY_THEN_FETCH, indices=[item_list], indicesOptions=IndicesOptions[ignore_unavailable=false, allow_no_indices=true, expand_wildcards_open=true, expand_wildcards_closed=false, allow_aliases_to_multiple_indices=true, forbid_closed_indices=true, ignore_aliases=false, ignore_throttled=true], types=[], routing='null', preference='null', requestCache=null, scroll=null, maxConcurrentShardRequests=0, batchedReduceSize=512, preFilterShardSize=128, allowPartialSearchResults=null, localClusterAlias=null, getOrCreateAbsoluteStartMillis=-1, ccsMinimizeRoundtrips=true, source={"size":10,"query":{"bool":{"should":[{"match":{"itemName":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameKana":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}},{"match":{"itemNameHira":{"query":"Entrez un mot de recherche","operator":"OR","prefix_length":0,"max_expansions":50,"fuzzy_transpositions":true,"lenient":false,"zero_terms_query":"NONE","auto_generate_synonyms_phrase_query":true,"boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}},"sort":[{"_score":{"order":"desc"}}]}}

C'était. Après la source, je l'ai confirmé en vérifiant le contenu de searchSourceBuilder, donc je l'ai exclu.

En ce qui concerne, si vous regardez les principaux éléments,

  • searchType
  • indicesOptions

n'est-ce pas.

Pour searchType,

Il y a une description dans.

Pour les indicesOptions,

Je ne pense pas que ce soit un peu différent, mais

N'est-ce pas.

Parmi ceux-ci, le searchType était clairement indiqué en ce qui concerne le score (_score). (En ce qui concerne indicesOptions, je n'ai rien trouvé sur le score (_score) pour autant que j'ai regardé autour de moi.)

La page mentionnée ci-dessus, Type de recherche (Elasticsearch Reference [6.8]) | élastique Dans la section "Dfs, interroger puis récupérer" de

・ ・ ・ Score plus précis.

Parce qu'il y en a, j'ai décidé de définir ceci qui semble donner un score plus précis. (Après "Correspondance")

Contenu de la correspondance

D'après les résultats de l'enquête, nous avons constaté qu'il semble nécessaire de corriger le contenu de SearchType, nous y répondrons donc. Définissez le searchType de SearchRequest sur "Dfs, Query Then Fetch" (où "Additional" est écrit).

Code source Java (après modification)


	/**
	 *Recherche de produit
	 *
	 * @mot-clé param mot-clé
	 * @nom d'index d'index de paramètre
	 * @nombre limite de paramètre
	 * @client param client de connexion Elasticsearch
	 * @renvoyer les résultats de la recherche
	 * @throws IOException
	 */
	public SearchResponse search(String keyword, String index, int limit, RestHighLevelClient client) throws IOException{

		//Initialiser les conditions de recherche
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

		BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

		boolQueryBuilder.should(QueryBuilders.matchQuery("itemName", keyword))
						.should(QueryBuilders.matchQuery("itemNameKana", keyword))
						.should(QueryBuilders.matchQuery("itemNameHira", keyword));

		searchSourceBuilder.query(boolQueryBuilder);
		//Réglage de l'ordre de tri (trier par score)
		searchSourceBuilder.sort(new FieldSortBuilder("_score").order(SortOrder.DESC));
		//Définissez le nombre de retours
		searchSourceBuilder.size(limit);

		SearchRequest request = new SearchRequest(index).source(searchSourceBuilder);
		//Type de recherche Dfs,Définir sur Interroger puis récupérer//Postscript
		request.searchType(SearchType.DFS_QUERY_THEN_FETCH); //Postscript
		return client.search(request, RequestOptions.DEFAULT);


	}

Et quand j'ai essayé de le déplacer, le résultat était comme prévu (identique à la requête d'exécution dans Kibana)! Le problème est résolu en toute sécurité! !!

Conclusion

La bonne réponse cette fois était de définir le searchType du SearchRequest sur "Dfs, Query Then Fetch". Au début, j'étais impatient car je ne pouvais pas obtenir le résultat attendu, mais je suis content d'avoir pu le résoudre.

référence

Bien que cela n'apparaisse pas dans le texte, il s'agit d'une liste d'articles auxquels j'ai fait référence.

Recommended Posts

[Recherche élastique x Java] Le résultat de l'exécution de la requête acquise en Java étant différent de l'hypothèse, j'ai étudié → Résumé du contenu correspondant
Obtenez le résultat de POST en Java
Résumé des points qui m'inquiétaient lors de la migration de Java vers Kotlin
La partie à laquelle j'étais accro dans "Introduction à Ajax dans les applications Web Java" de NetBeans
Je veux recréer le contenu des actifs à partir de zéro dans l'environnement construit avec capistrano
A été effectué dans l'année de base de la semaine calendaire Java
Quand j'étais inquiet des méthodes statiques dans l'interface java, je suis arrivé à l'ordre d'interprétation des noms