ElasticsearchでJava APIを使った完全一致検索


ElasticsearchのVer5.0以前では、完全一致検索を実現するためにはマッピングを作成する必要がありました。しかし、Ver5.0以降では、データを登録するとテキスト形式のデータには自動的に全文検索用のフィールドと完全一致用のフィールドが作成されるようになり、完全一致検索を行うのがとても便利になりました。



Elasticsearchのマッピング



ElasticsearchでJava APIを使ってインデックスに登録するのページで使った、社員データの構造を見てみます。Javaのクラスを利用してElasticsearchにデータを登録したときに、自動的に生成されたマッピング構造になります。



{ "test": { "aliases": {}, "mappings": { ] "employees": { "properties": { "department": { "properties": { "department_id": { "type": "long" }, "name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, "employee_id": { "type": "long" }, "name": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }


nameフィールドの箇所を見てみます。"type": "text"となっているので、ここは全文検索のフィールドになります。


さらにその中に"type": "keyword"となっているkeywordフィールドができています。ここが完全一致検索を行うためのフィールドになります。

"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}


実際にこのマッピング構造を持つインデックスに対して、Java APIを使って検索を行ってみましょう。以下に実際のプログラムを掲載します。




import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

public class TestSearch {

public static void main(String[] args){
TestSearch search = new TestSearch();
search.search();
}

/**
* Elasticsearchに接続する。
*
* @return TransportClient
*/
public TransportClient getESConnection(){
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
try {
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return client;
}


/**
* 検索を実行する。
*
* @return
*/
public void search(){
TransportClient client = getESConnection();
SearchRequestBuilder request = client.prepareSearch("test").setTypes("employees");
QueryBuilder query = QueryBuilders.termQuery("name.keyword","山田康夫");
SearchResponse response = request.setQuery(query).execute().actionGet();
SearchHits hits = response.getHits();
for(SearchHit hit : hits){
Map<String, Object> map = hit.getSource();
System.out.println(hit.sourceAsString());
}
}

}



Java APIで検索するときのポイント


完全一致検索を行うためには、Java APIではQueryBuilders.termQuery()を使います。


社員名を検索する場合にはnameフィールドを指定しますが、これだけでは全文検索になってしまいます。完全一致で検索する場合には「name.keyword」と指定する必要があります。


[完全一致検索]

QueryBuilder query = QueryBuilders.termQuery("name.keyword","山田康夫");


以下のものは正しく動作しません。

QueryBuilder query = QueryBuilders.termQuery("name","山田康夫");



もし、このフィールドに対して全文検索を行いたいのであれば以下のようにします。

[全文検索]

QueryBuilder query = QueryBuilders.matchQuery("name","山田康夫");




まとめ


Ver5.0以降は、何も考えなくても全文検索と完全一致検索のフィールドが作成されるようになったので、とても便利になりました。

検索がずいぶんやりやすくなったので、仕事がはかどりそうです。




関連記事 

1.ElasticsearchでJava APIを使ってインデックスに登録する


このエントリーをはてなブックマークに追加


▲ このページの上部へ戻る