[elasticsearch] Java API : Search
Elastic/Elasticsearch 2013. 4. 15. 11:36본 문서는 개인적인 테스트와 elasticsearch.org 그리고 community 등을 참고해서 작성된 것이며,
정보 교환이 목적입니다.
잘못된 부분에 대해서는 지적 부탁 드립니다.
(예시 코드는 성능 및 보안 검증이 되지 않았습니다.)
[elasticsearch java api 리뷰]
원문 링크 : http://www.elasticsearch.org/guide/reference/java-api/search/
- 이 API는 검색 쿼리를 실행 할 수 있으며, 쿼리와 일치하는 결과를 구할 수 있습니다.
원문 예제 부터 살펴 보겠습니다.
SearchResponse response = client.prepareSearch("index1", "index2")
.setTypes("type1", "type2")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(QueryBuilders.termQuery("multi", "test")) // Query
.setFilter(FilterBuilders.rangeFilter("age").from(12).to(18)) // Filter
.setFrom(0).setSize(60).setExplain(true)
.execute()
.actionGet();
- 두 개의 색인 파일에 대한 검색 조건을 생성 합니다. (index1 과 index2)
- 역시 각 index 에 대한 type을 지정 합니다.
- REST 방식으로 표현하게 되면 http://localhost:9200/index1,inde2/type1,type2/_search?....... 과 같이 됩니다.
- http://www.elasticsearch.org/guide/reference/api/search/indices-types/
- termQuery 에서 multi 라는 field 에 test 라는 term 을 찾게 됩니다.
/**
* A Query that matches documents containing a term.
*
* @param name The name of the field
* @param value The value of the term
*/
public static TermQueryBuilder termQuery(String name, String value) {
return new TermQueryBuilder(name, value);
}
[Operation Threading Model]
- NO_THREADS : 호출된 쓰레드에서 실행
- SINGLE_THREAD : 또 다른 하나의 쓰레드를 생성하여 모든 shard 를 조회
- THREAD_PER_SHARD : 각 개별 shard 별로 쓰레드를 생성하여 실행
- Default SINGLE_THREAD 로 설정이 되어 있고, 성능적인 확인은 필요함.
[MultiSearch API]
SearchRequestBuilder srb1 = node.client()
.prepareSearch().setQuery(QueryBuilders.queryString("elasticsearch")).setSize(1);
SearchRequestBuilder srb2 = node.client()
.prepareSearch().setQuery(QueryBuilders.matchQuery("name", "kimchy")).setSize(1);
MultiSearchResponse sr = node.client().prepareMultiSearch()
.add(srb1)
.add(srb2)
.execute().actionGet();
// You will get all individual responses from MultiSearchResponse#responses()
long nbHits = 0;
for (MultiSearchResponse.Item item : sr.responses()) {
SearchResponse response = item.response();
nbHits += response.hits().totalHits();
}
- 개별 검색 조건에 대한 한번의 요청으로 각각의 검색 결과를 얻을 수 있습니다.
[Using Facets]
- http://www.elasticsearch.org/guide/reference/java-api/facets/
SearchResponse sr = node.client().prepareSearch()
.setQuery(QueryBuilders.matchAllQuery())
.addFacet(FacetBuilders.termsFacet("f1").field("field"))
.addFacet(FacetBuilders.dateHistogramFacet("f2").field("birth").interval("year"))
.execute().actionGet();
// Get your facet results
TermsFacet f1 = (TermsFacet) sr.facets().facetsAsMap().get("f1");
DateHistogramFacet f2 = (DateHistogramFacet) sr.facets().facetsAsMap().get("f2");
- facet 검색은 검색 결과에 대한 분류 또는 그룹핑으로 이해 하시면 접근 하시는데 조금 쉽습니다.
- termsFacet("f1") 에서 f1 은 facet name 입니다.
아래 부터는 테스트로 작성한 코드 입니다.
참고용으로만 사용하시기 바랍니다.
[기본 Query Search]
response = client.prepareSearch("facebook")
.setOperationThreading(SearchOperationThreading.THREAD_PER_SHARD)
.setRouting("1365503894967")
.setTypes("post")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(QueryBuilders.termQuery("title", "9"))
.setFrom(0)
.setSize(20)
.setExplain(true)
.execute()
.actionGet();
log.debug("{}", response);
[Multi Search]
SearchRequestBuilder srb1 = client
.prepareSearch("facebook").setQuery(QueryBuilders.queryString("93").field("title")).setSize(1);
SearchRequestBuilder srb2 = client
.prepareSearch("facebook").setQuery(QueryBuilders.matchQuery("title", "94")).setSize(1);
MultiSearchResponse sr = client.prepareMultiSearch()
.add(srb1)
.add(srb2)
.execute().actionGet();
// You will get all individual responses from MultiSearchResponse#responses()
long nbHits = 0;
for (MultiSearchResponse.Item item : sr.responses()) {
response = item.response();
log.debug("{}", response);
}
[MatchQeury]
response = client.prepareSearch("facebook")
.setOperationThreading(SearchOperationThreading.THREAD_PER_SHARD)
.setTypes("post")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(
QueryBuilders.matchQuery("title", "1365577624100 twitter")
.type(Type.BOOLEAN) // default, PHASE 와 PHARE_PREFIX 는 하나의 TERM 으로 매칭.
.analyzer("gruter_analyzer") // analyzer는 지정 하지 않으면 settings 값으로 동작 함.
.operator(Operator.OR) // query 에 대한 token 연산을 의미 함.
)
.setFrom(0)
.setSize(5)
.setExplain(false)
.execute()
.actionGet();
log.debug("{}", response);
[Multi MatchQuery]
response = client.prepareSearch("facebook")
.setOperationThreading(SearchOperationThreading.THREAD_PER_SHARD)
.setTypes("post")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(
QueryBuilders.multiMatchQuery("136557762410", "docid", "title") // 각 field 에 대해서 matchQuery 를 수행 하는 것과 같은 효과.
.type(Type.PHRASE_PREFIX)
.operator(Operator.OR)
)
.setFrom(0)
.setSize(14)
.setExplain(false)
.execute()
.actionGet();
log.debug("{}", response);
[Facet Search]
response = client.prepareSearch("blog")
.setQuery(QueryBuilders.matchAllQuery())
.addFacet(FacetBuilders.termsFacet("facetYear").field("year"))
.addFacet(FacetBuilders.termsFacet("facetMonth").field("month"))
.addFacet(FacetBuilders.termsFacet("facetDay").field("day"))
.execute()
.actionGet();
TermsFacet facetYear = (TermsFacet) response.facets().facetsAsMap().get("facetYear");
TermsFacet facetMonth = (TermsFacet) response.facets().facetsAsMap().get("facetMonth");
TermsFacet facetDay = (TermsFacet) response.facets().facetsAsMap().get("facetDay");
log.debug("{}", response);
- facet search 테스트를 위한 scheme 정보는 아래와 같습니다.
"mappings" : {
"post" : {
"properties" : {
"docid" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },
"title" : { "type" : "string", "store" : "yes", "index" : "analyzed", "term_vector" : "yes", "analyzer" : "gruter_analyzer", "include_in_all" : false },
"year" : { "type" : "integer", "store" : "no", "index" : "not_analyzed", "include_in_all" : false },
"month" : { "type" : "integer", "store" : "no", "index" : "not_analyzed", "include_in_all" : false },
"day" : { "type" : "integer", "store" : "no", "index" : "not_analyzed", "include_in_all" : false }
}
}
}