즐겁게/elasticsearch-8

Query, SearchRequest를 이용한 검색

파이브빈즈 2022. 10. 17. 20:54

elasticsearch에서 Query를 이용하여 지난글에서 추가한 Board를 검색

 

참조: IndexRequest를 이용한 Document 추가

 

IndexRequest를 이용한 Document 추가

Board와 Author 라는 게시판, 작성자 클래스가 있다고 할때 이를 이용하여 Index에 추가를 할수 있음 @Setter @Getter public class Board { private int idx; private String category; private String subject; private String body; priva

realkoy.tistory.com

public void search() {
	ElasticsearchClient client = null;
	try {
		// Index name to search
		String indexName = "test-Index";

		Query termQry = TermQuery.of(t -> t.field("category").value(FieldValue.of("자유게시판")))._toQuery();		
		//Query termQry = QueryBuilders.term().field("category").value(FieldValue.of("자유게시판")).build()._toQuery();
		//Query termQry = new TermQuery.Builder().field("category").value("자유게시판").build()._toQuery();
		
		Query wildQry = WildcardQuery.of(w -> w.field("subject").wildcard("*KAKAO*"))._toQuery();
		//Query wildQry = QueryBuilders.wildcard().field("subject").wildcard("*KAKAO*").build()._toQuery();
		//Query wildQry = new WildcardQuery.Builder().field("subject").wildcard("*KAKAO*").build()._toQuery();

		Query matchQry = MatchQuery.of(t -> t.field("body").query("카카오"))._toQuery();	
		//Query matchQry = QueryBuilders.match().field("body").query("카카오").build()._toQuery();	
		//Query matchQry = new MatchQuery.Builder().field("body").query("카카오").build()._toQuery();	

		Query rangeQry = RangeQuery.of(r -> r.field("date").from("2022-10-01 10:00:00").to("2022-10-10 23:00:00").format("yyyy-MM-dd HH:mm:ss"))._toQuery();
		//Query rangeQry = QueryBuilders.range().field("date").from("2022-10-01 10:00:00").to("2022-10-10 23:00:00").format("yyyy-MM-dd HH:mm:ss").build()._toQuery();
		//Query rangeQry = new RangeQuery.Builder().field("date").from("2022-10-01 10:00:00").to("2022-10-10 23:00:00").format("yyyy-MM-dd HH:mm:ss").build()._toQuery();
		
		List<Query> listQry = new ArrayList<>();
		listQry.add(termQry);
		listQry.add(wildQry);
		listQry.add(matchQry);
		listQry.add(rangeQry);

		Query nestTermQry = NestedQuery.of(n -> n.path("author").query(q -> q.term( t -> t.field("author.name").value("홍길동"))))._toQuery();
		Query nestWildQry = NestedQuery.of(n -> n.path("author").query(q -> q.wildcard( t -> t.field("author.email").value("*kakao*"))))._toQuery();
		
		List<Query> listNestQry = new ArrayList<>();
		listNestQry.add(nestTermQry);
		listNestQry.add(nestWildQry);

		Query qry = new Query.Builder()
			.bool(b -> b
				.must(listQry)
				.should(listNestQry).minimumShouldMatch("1")
			)
			.build();

		// ElasticSearchClient
		client = ElasticClient.getInstacne();
        
		// 전체개수
		CountRequest countRequest = new CountRequest.Builder().index(indexName).query(qry).build();
		CountResponse countResponse = client.count(countRequest);
		long totalCount = countResponse.count();

		// from, size 를 이용하여 게시판처럼 구현 가능
		SearchResponse<Board> response = client.search(s -> s
			.index(indexName)
			// trackTotalHits를 이용하면 max_result_window 제한을 벗어나서 전체 개수를 구할수 있으나,
			// CountRequest를 이용하여 totalCount를 구하는 것이 효율적
			//.trackTotalHits(t -> t.count(Integer.MAX_VALUE))
			.query(qry)				
			.from(0).size(20)
			.sort(so -> so.field(f -> f.field("date").order(SortOrder.Desc)))
			,Board.class);

		// max_result_window 이하
		// long totalCount = response.hits().total().value();

		// 한개씩 출력
		for (Hit<Board> hit: response.hits().hits()) {
			// Board
			Board board = hit.source();

			System.out.println(hit.id() + ". Category: " + board.getCategory() + " - Subject: " + board.getSubject());

			// Nested : Author
			if(board.getAuthor() != null) System.out.println( "  Author: " + board.getAuthor()[0].getName() + " / " + board.getAuthor()[0].getEmail());
		}

	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		ElasticClient.close();
	}
}