Elasticsearch & Query DSL
Written By Nuri Na, VCANUS
About
-
JVM: Elasticsearch는 자바 애플리케이션으로 Java 설치 필요
-
HTTP / RESTful API: REST API를 통해 조작
-
JSON: 내부에 JSON으로 저장, 요청/응답도 JSON 형식
-
역색인(Inverted Index) 구조: 단어 검색 시 해당 단어가 포함된 모든 document를 가리킴
-
Index/type/document : 엘라스틱 서치의 데이터 계층.
/<indexName>/<typeName>/<documentName>
로 표현
현재는 type를 구분하지 않도록 하고 있으며, /indexName/_doc
/documentName으로 사용
Indexing
인덱스 생성
//**Example**
PUT lecture // lecture 인덱스 생성
PUT lecture/_doc/1 // 인덱스가 없을 경우 인덱스 생성, title 필드에 value 저장 (Schemeless)
{
"title": "근대 중국사"
}
Mapping
인덱스에 필드와 데이터 포맷을 정의
가능한 데이터 타입은 text, keyword, date, long, double, boolean, ip, geo_point 등
//**Example**
PUT lecture/_mapping
{
"properties":{
"title":{"type":"text"},
"professor":{"type":"text"},
"major":{ //text와 keyword 두 가지로 정의
"type":"text",
"fields": {
"raw": {
"type":"keyword" //fields.raw
}
}
},
"semester":{"type":"text"},
"student_count":{"type":"integer"},
"unit":{"type":"integer"},
"rating":{"type":"integer"},
"report_due_date":{"type":"date","format":"yyyy-MM-dd"},
"school_location":{"type":"geo_point"} //좌표값. lat/lon 키를 가짐. geohash 가능.
}
}
Insert/Update
//**Example**
PUT lecture/_doc/1
{
"title": "중국 고전 강독",
"professor": "나민구",
"major": "중국어", // text와 keyword 두 가지 타입으로 mapping
"semester": "1학기",
"student_count": 20,
"unit": 5,
"rating": 8,
"report_due_date": "2020-03-10",
"school_location": {
"lat":37.401376,
"lon":127.110516
}
}
PUT lecture/_doc/2
{
"title": "현대중국정치",
"professor": "오승렬",
"major": "중국어",
"semester": "1학기",
"student_count": 10,
"unit": 3,
"rating": 4,
"report_due_date": "2020-03-24",
"school_location": "drm3btev3e86" //geohash
}
URI Search
URL에 파라미터를 넘겨 문서 조회, 간단한 테스트에 유용
## Example
curl -XGET 'localhost:9200/<indexName>/_search?q=<검색어>&sort=<정렬기준>'
Query DSL
Request Body 검색에 이용되는 JSON 구조를 지원, 다양한 검색 조건 조합에 용이하며 재사용이 가능해 일반적으로 사용됨
Query DSL 구조
{
"size": //리턴 결과 개수 지정
"from": //몇 번째 문서부터 가져올 지 지정
"timeout": //결과 받는 데까지 걸리는 시간
"_source": //특정 필드만 출력하고 싶을 때 사용
"query" : { } //검색 조건문 작성
"aggs" : { } //통계 및 집계
"sort" : { } //출력 조건
}
* 아래 예시의 주석에 해당하는 번호를 확인할 것
//**Example**
// SELECT title FROM ( SELECT * FROM lecture WHERE major = '중국어' )
// WHERE title = '%현대%' OR title = '%중국%';
POST lecture/_search
{
"from": 0, //첫 페이지부터
"size": 5, //다섯 개 문서만 조회
"query": { //2. 쿼리 컨텍스트
"bool": {
"must": [ //1. 반드시 조건에 만족하는 문서만 검색
{
"match": { //3. match
"title": "현대 중국"
}
}
],
"filter": { //2. 필터 컨텍스트
"term": {
"major": "중국어"
}
}
}
},
"_source": [ "title", "rating" ], //보고 싶은 필드만 필터링
"sort": [ //정렬
{
"rating": { "order": "asc" }
}
]
}
-
must 연산과 조건 쿼리
Elasticsearch SQL 설명 must : [field] AND = <조건>조건> 반드시 조건에 만족하는 문서만 must_not : [field] AND != <조건>조건> 조건을 만족하지 않는 문서 should : [field] OR = <조건>조건> 여러 조건 중 하나 이상 만족하는 문서 filter : [field] IN <조건>조건> 조건을 포함하는 문서 -
쿼리 컨텍스트와 필터 컨텍스트
쿼리 컨텍스트 필터 컨텍스트 용도 전문 검색 시 조건 검색 시 (Yes/No) 특징 분석기에 의해 분석
연관성 관련 Score를 계산
루씬 레벨에서 분석 - 상대적으로 느림Yes/No로 단순 판별
연관성 관련 계산 X
엘라스틱서치 레벨에서 분석 - 상대적으로 빠름사용 예 문장 분석 ‘major’ 필드 값이 ‘중국어’인지 여부 -
Match 쿼리 - 형태소 분석을 통해 term을 분리, 별도의 operator 필드가 없으면 term을 대상으로 OR 연산을 수행함
// cf ) operator를 적용하는 경우
"match": {
"title": {
"query" : "현대 중국",
"operator" : "and"
}
}
Aggregations(집계)
SQL보다 강력한 집계 기능 제공 - 여러 aggs 중첩, 날짜/위치 정보 집계, 분산처리 등
집계 시 문서를 평가한 후 기준에 만족하는 문서를 그룹화 하고, 그것을 토대로 집계 수행
집계 구문 구조
{
"query": { ... },
"aggregations" : { ... } //혹은 aggs
}
"aggregations": {
"집계 이름":{
"집계 타입":{ //terms, date_histogram, sum ...
집계 타입에 맞는 조건 내용
},
[, "meta" : { 메타 데이터 조건 내용 }]? //메타 필드 가능
[, "aggregations" : { [ 서브 집계 ]+ } ]? //서브 집계 가능
}
[,"집계 이름2" : { ... }]* //집계 중첩 가능
}
//**Example**
// SELECT avg(rating) as average_rating FROM lecture GROUP BY ranges;
POST lecture/_search
{
"size": 0, //집계된 문서들의 데이터는 불필요하므로 0
"aggs": {
"group_by_student_count": { //그룹화
"range": {
"field": "student_count",
"ranges": [
{ "from": 0, // 이상 (<=)
"to": 11 }, // 미만 (<)
{ "from": 11,
"to": 21 }
]
},
"aggs": { //집계
"average_rating": {
"avg": { "field": "rating" }
}
}
}
}
}
// SELECT major, avg(rating) from lecture GROUP BY major;
GET lecture/_search?size=0 // get/post 섞어서 쓸 수 있음
{
"aggs": {
"group_by_major":{ //그룹화
"terms":{
"field": "major.raw",
"order" : { "_key" : "asc" }
},
"aggs": { //집계
"average_rating":{
"avg":{ "field": "rating" }
}
}
}
}
}
확장 통계 집계
GET lecture/_search?size=0
{
"aggs":{
"mongtangda": {
"extended_stats": { //count, min, max, avg, sum 외 제곱합, 분산, 표준편차 등..
"field": "student_count"
}
}
}
}
Shards & Replicas
PUT lecture
{
"settings":{
"index": {
"number_of_shards": 3,
"number_of_replicas": 0
}
}
}
Leave a comment