[Elasticsearch] Query Dsl
안녕하세요. 오늘은 Query Dsl에서 가장 중요하다고 생각하는 Query에 대한 기본적인 이론에 대해서 알아보도록 하겠습니다. 해당 부분을 본 후에는 Elasticsearch 검색 쿼리를 작성할 때 매핑된 타입 값에 따라서 해당 부분을 참고하면 좋을 것 같습니다.
Query는 크게 세가지로 나눠질 수 있습니다.
1. Query Context
- 정의
: Full text search를 의미하며, 검색어가 문서의 얼마나 매칭 되는지를 표현하여 hit score라는 값을 가진다. ex) 도서관에서 책의 내용을 바탕으로 가장 비슷한 책을 검색할 때 사용할 수 있습니다.
- 쿼리(중요하다고 생각하는 부분만 예시 쿼리를 써놨습니다.)
- match : 검색어로 들어온 문자열을 analyzer로 분석 후 해당 토큰들을 inverted index에서 문서를 검색할 수 있다.
- analyzer을 바탕으로 Hello Elasticsearch는 토큰들로 분리됩니다. 그래서 inverted index에서 hello가 있는 doc과 elasticsearch가 있는 doc의 id값을 각각 수집하여 통합하여 클라이언트 노드로 결괏값을 보냅니다.
-
{ "query": { "match":{ "검색필드1":"Hello Elasticsearch" } } }
- match_phrase : 나눠진 토큰들의 순서로 고려해서 search 한다. 그래서 검색하고자 하는 문자열의 전체 토큰을 가진 문서만 검색된다.
- analyzer을 바탕으로 Hello Elasticsearch는 토큰들로 분리됩니다. 그래서 inverted index에서 hello와 elasticsearch가 함께 있는 doc의 id값을 수집하여 클라이언트 노드로 결과값을 보냅니다.
-
{ "query":{ "match_phrase":{ "검색 필드값": "Hello Elasticsearch" } } }
- multi_match : 두 개 이상의 필드에 match 쿼리를 날릴 수 있습니다.
- match와 동일하지만 두 개 이상의 필드에 match 쿼리 날릴 수 있습니다.
-
{ "query":{ "multi_match":{ "query": "Helo Elasticsearch", "fields" : [검색 필드값1, 검색 필드값2] } } }
- query_string : match와 multi_match처럼 동일하게 동작할 수 있으며, and와 or 쿼리로 동작할 수 있습니다. 하지만 wildcard를 붙이는 부분은 비효율 적일 수 있으므로 되도록이면, match를 쓰거나 다른 쿼리를 쓰도록 하자.
-
{ "query":{ "query_string":{ "fields": ["title"], "query":"*nux" } } }
-
2. Filter Context(Term Level Query)
- 정의
: 검색어가 문서에 존재하는지 여부를 yes나 no 형태의 검색결과로 보여준다. 쉽게 말해, 검색어에 해당 토큰의 포함 여부를 찾는 형태이다. score 값을 가지지 않는다. 도서관에서 정확한 책의 제목을 바탕으로 책의 유무를 검색할 때 사용합니다. 또한, analyzer 과정을 거치지 않아서 대소문자 구분 및 빠르게 동작할 수 있습니다.
- 쿼리(중요하다고 생각하는 부분만 예시 쿼리를 써놨습니다.)
- term : 검색어로 입력한 단어와 정확하게 일치하는 단어가 있는 문서를 찾는다.
- inverted index에 analyzer 하지 않은 검색어로 검색하기 때문에 색인된 데이터는 analyzer 된 데이터이므로 정확하게 일치하는 것을 찾아야 한다.
-
{ "query":{ "term":{ "검색 필드값": "Hello Elasticsearch" } } }
- terms : 둘 이상의 term 쿼리를 사용할 때 사용하는 쿼리이다.
- range : 범위를 지정하여 특정 값의 범위 이내에 있는 경우를 검색할 때 사용합니다.
-
{ "query":{ "range":{ "date":{ "gte": "2021/11/1", "lte": "2021/12/1" } } } }
-
- wildcard : 와일드카드 특수문자를 이용한 Full Scan 검색을 하는 방법이다. 하지만 wildcard query는 모든 inverted index를 하나하나 확인하기 때문에 검색 속도가 매우 느립니다. 그래서 keyword 타입에서 사용하며 match를 사용할 수 있으면 match 쿼리를 사용하는 편이 빠르다.
-
{ "query":{ "wildcard":{ "검색 필드값": "Hello*" } } }
-
3. Bool query
- 정의
: Query Context와 Filter Context를 조합해서 사용할 수 있는 방법입니다. 주의할 점은 위에서 query context와 filter context의 차이를 살펴봤습니다. 스코어링이 필요한 구문은 must와 should에 넣는 것이, 스코어링이 필요하지 않은 filter context는 filter절에 넣는 것이 조금 더 효과적으로 쿼리를 날릴 수 있습니다.
- 예시
{
"query": {
"bool": {
"filter": [
{
"term": {
"검색필드": "검색값"
}
},
{
"term": {
"검색필드2": "검색값2"
}
}
],
"must": [
{
"match": {
"검색필드3": "검색값3"
}
}
]
}
}
}
- 쿼리
1. must : 항목 내 쿼리에 일치하는 문서를 검색합니다.
2. filter : 항목 내 쿼리에 일치하는 문서를 검색합니다.
3. should : 항목 내 쿼리에 일치하는 문서를 검색합니다.
4. must_not : 항목 내 쿼리에 일치하는 문서를 검색합니다.