자소 단위로 한글 검색을 구현하기 위해 아래의 플러그인을 이용하였습니다.
https://github.com/netcrazy/elasticsearch-jaso-analyzer
FROM elasticsearch:6.6.0
RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v6.6.0/jaso-analyzer-plugin-6.6.0.0-plugin.zip
Dockerfile을 작성한 뒤,
$ docker build --tag elasticsearch-custom .
빌드합니다.
$ docker run -p 9200:9200 -p 9300:9300 --name elasticsearch-custom -e "discovery.type=single-node" elasticsearch-custom
컨테이너를 구동합니다.
http://<IP주소>:9200/ 접속이 잘 됩니다.
해당 플러그인 사용법에 따라 설정을 하겠습니다.
$ curl -XPUT -H 'Content-Type: application/json' http://192.168.99.100:9200/search_logs/ -d '{
"settings": {
"index": {
"analysis": {
"filter": {
"suggest_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 50
}
},
"tokenizer": {
"jaso_search_tokenizer": {
"type": "jaso_tokenizer",
"mistype": true,
"chosung": false
},
"jaso_index_tokenizer": {
"type": "jaso_tokenizer",
"mistype": true,
"chosung": true
}
},
"analyzer": {
"suggest_search_analyzer": {
"type": "custom",
"tokenizer": "jaso_search_tokenizer"
},
"suggest_index_analyzer": {
"type": "custom",
"tokenizer": "jaso_index_tokenizer",
"filter": [
"suggest_filter"
]
}
}
}
}
}
}'
인덱스를 생성해줍니다.
$ curl -XPUT -H 'Content-Type: application/json' http://192.168.99.100:9200/search_logs/_mapping/search_log -d '{
"properties": {
"log": {
"type": "text",
"store": true,
"analyzer": "suggest_index_analyzer",
"search_analyzer": "suggest_search_analyzer",
"fields" : {
"raw" : {"type":"keyword"}
}
},
"category": {
"type": "keyword"
},
"timestamp": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}'
"log" 필드에서 한글 검색을 수행할 것입니다.
기능을 구현하다보니 "text" 타입에는 aggregation을 이용할 수 없었습니다.
그래서 "fields" 속성 하위에 "raw" 속성을 추가하였습니다.
이렇게 하면 "log.raw"를 이용하여 "keyword"타입으로도 aggregation 할 수 있습니다.
이를 이용하여 express로 구현하고 있는 서버에 자동완성기능과 인기검색어를 구현하고자 하였습니다.
var items = [];
var result = await client.search({
index : 'search_logs',
type : 'search_log',
body : {
"query" : {
"match" : {"log" : query}
},
"aggs" : {
"byCount" : {
"terms" : {
"field" : "log.raw",
"size" : 15,
"order" : { "_count" : "desc" }
}
}
},
"size" : 0
}
});
items = result.body.aggregations.byCount.buckets.map(x => x.key);
res.json({result:items});
자동완성 기능을 구현하기위한 예시 코드입니다.
쿼리로 받은 스트링을 이용하여 검색을 수행하고, aggregation을 이용하여 "log"의 중복을 제거한 뒤, count순으로 정렬합니다.
//"자ㅈ"로 데이터 조회 결과
{
"result": [
"자점석",
"자전거"
]
}
수집된 로그를 바탕으로 "자ㅈ"의 검색 결과입니다.
var result = await client.search({
index : 'search_logs',
type : 'search_log',
body : {
"aggs" : {
"byCount" : {
"terms" : {
"field" : "log.raw",
"order" : {"_count" : "desc"},
"size":numOfQuery
}
}
},
"size" : 0
}
});
items = result.body.aggregations.byCount.buckets.map(x => x.key);
res.json({result : items});
인기 검색어를 구현하기 위한 예시 코드입니다.
최근 수집된 검색어 데이터에서 중복을 제거하고, count 순으로 조회를 하려고 하였지만, aggregation 파이프라인을 구현하는 중에 자꾸 오류가 났습니다.
그래서 일단 중복을 제거시키고 count 순으로 조회하였습니다.
// 조회 결과
{
"result": [
"안녕",
"자점석",
"자전거",
"가",
"자",
"하"
]
}
수집된 검색어 로그의 count 순으로 정렬되어 결과가 나옵니다.
* 플러그인 버전과 맞추기위해 이전 버전의 elasticsearch를 이용하였습니다.
* 예전에 제대로 된 학습이 되지 않은 채로, 단순 기능 구현만을 목적으로 진행하며 작성했던 내용이라 좋은 방법이 아닐 수 있습니다.
'Express' 카테고리의 다른 글
Node.js Express Swagger 이용하여 API 문서 만들기 (0) | 2021.11.10 |
---|---|
Node.js Express multer-s3를 이용한 이미지 업로드 및 이미지 삭제 (0) | 2021.11.10 |
Node.js multer를 이용한 이미지 업로드 및 sharp를 이용한 이미지 리사이징 (0) | 2021.11.10 |