이번에 문서 검색 기능을 개발할 일이 생겼는데 단순 단어매칭 보다는 고도화된 검색엔진이 필요하여 Elasticsearch를 알아보게 되었다.
Elasticsearch란?
Elasticsearch는 정형, 비정형 데이터 등의 모든 type의 데이터를 위한 검색 및 분석엔진이다. 대용량의 데이터를 다룰 수 있도록 분산형 feature들이 발달되어 있으며 REST API를 통해 데이터 조회, 입력, 삭제를 처리한다.
Installation
당분간은 개발용으로만 사용할 예정이지만 추후 서비스 가능성을 고려해 docker로 설치하려 한다. 설치 명령어는 Elasticsearch의 quick start 를 참고하였다.
docker network create elastic
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.13.3
번거롭지만 docker container가 사용할 데이터 파일의 경로를 정해주기 위해 아래의 docker-compose.yml을 작성하여 실행을 하였다. (SSD 용량이 거의 다 차서 HDD에 데이터를 저장할 목적)
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.4
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.4
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.4
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
networks:
- elastic
volumes:
data01:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/elasticsearch-data/data01
data02:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/elasticsearch-data/data02
data03:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/elasticsearch-data/data03
networks:
elastic:
driver: bridge
volumes의 device 경로는 임의로 설정할 수 있다. 용량이 넉넉한 디바이스로 지정하도록 하자.
설치가 잘 되었는지는 아래의 명령어로 확인할 수 있다.
curl -X GET http://localhost:9200/
Index 생성
설치가 제대로 되었다면 다음으로 할 일은 RDBMS의 database에 해당하는 index를 만들어야 한다. BM25 알고리즘 기반의 고도화된 검색엔진을 사용하기 위해서 similarity type을 BM25로 셋팅하여 index를 만들었다. 다른 파이썬 코드와 쉽게 연동하기 위해 필자는 아래 코드와 같이 파이썬으로 PUT request를 보냈다.
위의 명령어로 설치를 완료하였다면 elastic_url은 http://localhost:9200/ 이 된다.
import json
import requests
def create_bm25_idx(elastic_url, idx_name):
req_url = '%s/%s' % (elastic_url, idx_name)
data = {
'settings': {
'number_of_shards': 1,
'index': {
'similarity': {
'default': {
'type': 'BM25'
}
}
}
}
}
headers = {'Content-Type': 'application/json'}
req = requests.put(req_url,
data=json.dumps(data),
headers=headers)
print(req.text)
Document 추가
다음은 document를 추가하는 함수를 작성할 차례이다. 위와 마찬가지로 파이썬으로 작성하였으며, 세 번째 인자로 파이썬 딕셔너리를 받아 json으로 변환 후 post 요청을 보내도록 구현하였다.
def add_doc(elastic_url, idx_name, doc):
req_url = '%s/%s/_doc' % (elastic_url, idx_name)
headers = {'Content-Type': 'application/json'}
req = requests.post(req_url,
data=json.dumps(doc),
headers=headers)
print(req.text)
Search
마지막으로 검색 함수를 작성한다. 검색 url은 index 경로 뒤에 _search를 붙여 만들 수 있다. 아래의 함수에서 attr_name은 컬럼명이고 query는 검색어이다.
def search(elastic_url, idx_name, query, attr_name):
req_url = '%s/%s/_search?pretty' % (elastic_url, idx_name)
data = {
'query': {
'match': {
attr_name: query
}
}
}
headers = {'Content-Type': 'application/json'}
req = requests.get(req_url,
data=json.dumps(data),
headers=headers)
print(req.text)
검색의 추가적인 옵션은 elasticsearch 공식 문서를 참고하도록 하자.
인증, 암호화 적용
이 예제를 따라하면 사용자 인증기능과 https를 도입할 수 있다.
volume 셋팅은 위의 docker-compose.yml과 동일하게 적용할 수 있다.
'데이터 과학 > 데이터 과학 실무' 카테고리의 다른 글
elasticsearch 사용자 추가, 인덱스 접근권한 부여 (0) | 2021.07.28 |
---|