📌 SQL문으로 표현하면
SELECT * FROM boards WHERE board_id = 1
이와 같이 정확히 일치하는 값을 조회한다.
//인덱스 생성 / 매핑 정의
PUT /boards
{
"mappings": {
"properties": {
"board_id": {
"type": "long"
},
"category": {
"type": "keyword"
}
}
}
}
// 데이터 삽입
POST /boards/_doc
{
"board_id" : 1,
"category" : 자유 게시판
}
POST /boards/_doc
{
"board_id" : 2,
"category" : 익명 게시판
}
POST /boards/_doc
{
"board_id" : 3,
"category" : 광고 게시판
}
document 조회
GET /boards/_search
{
query:{
"term":{
"category" : "자유"
}
}
}
GET /boards/_search
{
"query": {
"term": {
"category": "자유게시판"
}
}
}
GET /boards/_search
{
"query": {
"term": {
"board_id": 13
}
}
}
// 이와 같이 검색했을 때 정확히 일치하는 데이터가 존재하지 않기 때문에 검색이 되지 않는다.
GET /boards/_search
{
"query": {
"term": {
"category": "자유 게시판"
}
}
}
GET /boards/_search
{
"query": {
"term": {
"board_id": 1
}
}
}
// 정확한 값으로 조회했을 때 검색이 된다.
SELECT * FROM boards WHERE category IN('자유 게시판', '익명 게시판');
GET /boards/_search
{
"query": {
"terms": {
"category": ["자유 게시판", "익명 게시판"]
}
}
}
// 배열로 검색
must : SQL문에서의
AND역할을 함
filter : SQL문에서의AND역할을 함
must_not : SQL문에서의NOT역할을 함
should : 조건을 만족하면 좋고, 아니면 말고
GET /boards/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"category": "자유 게시판"
}
},
{
"term": {
"board_id": 1
}
}
]
}
}
}
GET /boards/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"category": "자유 게시판"
}
},
{
"term": {
"board_id": 1
}
}
]
}
}
}
// 잘못된 must 쿼리 사용
filter와 must의 사용 용도는 score에 영향을 주는 쿼리인지 아닌지로 구분해서 사용해야 한다.
filter : score와 상관없는 쿼리 -> term
must : score와 상관있는 쿼리 -> match
점수(score)를 활용하는 쿼리는 text 타입을 기반으로 검색을 유연하게 해주는 쿼리(match, match_phrase, multi_match 등) 밖에 없다. 즉, 정확하게 일치하지 않더라도 관련성이 있는 데이터까지 조회하는 쿼리에 대해서만 must를 사용하면 된다. 그 외에는 전부 filter를 쓰면 된다.
text 타입, match 쿼리 → bool의 must→ `text` 이외의 타입, `term` 쿼리
→ `bool`의 `filter`
#### ✅ bool : must_not
- 특정 조건을 만족하지 않는 데이터를 조회하고 싶을 때
```
GET /boards/_search {```GET /products/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "무선 이어폰"
}
}
],
"should": [
{
"range": {
"rating": {
"gte": 4.5 // 4.5 이상의 평점의 상품일 경우 score에 가산점 부여
}
}
},
{
"range": {
"likes": {
"gte": 100 // 좋아요 수가 100개 이상인 상품일 경우 score에 가산점 부여
}
}
}
]
}
}
}
// 결과
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 2.5864,
"hits": [
{
"_index": "products",
"_id": "0E-AlZYBWhYNXJPWlr56",
"_score": 2.5864,
"_source": {
"name": "갤럭시 버즈2 무선 이어폰",
"rating": 4.8,
"likes": 310
}
},
{
"_index": "products",
"_id": "zk-AlZYBWhYNXJPWjb70",
"_score": 2.1297402,
"_source": {
"name": "무선 충전기 C타입",
"rating": 4.9,
"likes": 300
}
},
{
"_index": "products",
"_id": "z0-AlZYBWhYNXJPWkb6p",
"_score": 0.6409958,
"_source": {
"name": "소니 무선 이어폰 WF",
"rating": 3.8,
"likes": 15
}
}
]
}
}
``1번째 데이터 검색 키워드와 관련성이 높고, 평점이 높고, 좋아요 수도 높아 상위에 노출
2번째 데이터 검색 키워드와 관련성이 조금 낮지만 평점과 좋아요가 높아 3번째 데이터보다 상위에 노출
3번째 데이터 검색 키워드와 관련성이 높지만, 평점과 좋아요 수가 낮아 데이터가 제일 하위에 노출
이와 같이 score에 가산점을 주는 bool 쿼리의 should를 활용해 원하는 조건을 갖추고 있는 데이터를 상단에 노출되게 만들 수 있다.
GET /boards/_search
{
"query": {
"match": {
"title": {
"query": "elastiksearch",
"fuzziness": "AUTO"
}
}
}
}
fuzziness : AUTO : 단어 길이에 따라 오타 허용 개수를 자동으로 설정
-여러 필드 (예 제목/내용 등) 에서 검색 키워드가 포함된 데이터를 조회할 때
GET /boards/_search
{
"query": {
"multi_match": {
"query": "엘라스틱서치 적용 후기",
"fields": ["title", "content"]
}
}
}
GET /boards/_search
{
"query": {
"multi_match": {
"query": "엘라스틱서치 적용 후기",
"fields": ["title", "content"]
}
},
"highlight": {
"fields": {
"title": {
"pre_tags": ["<mark>"],
"post_tags": ["</mark>"]
},
"content": {
"pre_tags": ["<b>"],
"post_tags": ["</b>"]
}
}
}
}
{
"took": 19,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 3.79424,
"hits": [
{
"_index": "boards",
"_id": "2k-SmJYBWhYNXJPWbr6u",
"_score": 3.79424,
"_source": {
"title": "엘라스틱서치 적용 후기",
"content": "회사 프로젝트에 엘라스틱서치를 적용한 후기를 공유합니다."
},
"highlight": {
"title": [
"<mark>엘라스틱</mark><mark>서치</mark> <mark>적용</mark> <mark>후기</mark>"
],
"content": [
"회사 프로젝트에 <b>엘라스틱</b><b>서치</b>를 <b>적용</b>한 <b>후기</b>를 공유합니다."
]
}
},
{
"_index": "boards",
"_id": "3E-SmJYBWhYNXJPWd740",
"_score": 1.7749425,
"_source": {
"title": "검색엔진 도입 사례",
"content": "이번 프로젝트에 엘라스틱서치를 적용한 후 많은 개선 효과가 있었습니다."
},
"highlight": {
"content": [
"이번 프로젝트에 <b>엘라스틱</b><b>서치</b>를 <b>적용</b>한 후 많은 개선 효과가 있었습니다."
]
}
},
{
"_index": "boards",
"_id": "20-SmJYBWhYNXJPWc75z",
"_score": 1.3862942,
"_source": {
"title": "엘라스틱서치를 사용해보니",
"content": "검색 엔진 도입 후 성능이 향상되었습니다."
},
"highlight": {
"title": [
"<mark>엘라스틱</mark><mark>서치</mark>를 사용해보니"
]
}
}
]
}
}
// 검색 결과에 HTML 태그로 감싼 뒤 결과값을 반환.
// 이 결과값을 활용해서 웹 페이지에서 하이라이팅 처리를 하면 된다.
GET /boards/_search
{
"query": {
"match": {
"title": "글"
}
},
"size": 3,
"from": 0
}
size : 한 페이지에 불러올 데이터 개수 (SQL문의 LIMIT과 동일)
from : 몇 번째 데이터부터 불러올 지 (SQL문의 OFFSET과 동일, 0부터 시작)
- from = (페이지 수 - 1) x size
GET /boards/_search
{
"query": {
"match": {
"title": "글"
}
},
"sort": [
{
"likes": {
"order": "desc"
}
}
]
}
좋아요 수 기준 내림 차순 조회
GET /products/_search
{
"query": {
"multi_match": {
"query": "돌김",
"type": "bool_prefix",
"fields": [
"name",
"name._2gram",
"name._3gram"
]
}
}
}
서버의 자동완성 API를 타이핑 할 때마다 호출하여 자동완성 데이터를 반환한다.