[스핑크스 검색 엔진] docker 에서 돌리고 python으로 검색해 보기

아마도 검색엔진에 관해서 기억을 해 보면,
1990년대 초 KT 전자전화번호부 프로젝트를 진행하면서
씨소러스를 이용한 검색엔진을 직접 개발하면서 부터였습니다.
그 중간에 박사학위 따시는 분의 검색엔진 관련 구현을 해 준 적도 있었습니다.

2000년대 초 다시 검색엔진을 살펴보았을 때 아파치 Lucene 루씬 엔진을 이용한
FULL TEXT 전문검색을 하기도 했었습니다.

최근에 다시 필요에 따라 검색 엔진이 뭐가 있고 어떤 것을 이용해 볼 수 있을까
살펴보았습니다. 루씬 및 그것을 활용한 솔라도 여전히 있었고,
초창기 버전으로 이용해 보았던 스핑크스 검색 엔진도 여전히 있었습니다.

이번에는 스핑크스 검색엔진에 색인을 하는 방법과 pyMySQL 모듈을
이용하여 파이썬에서 검색을 하는 방법을 간단히 살펴봅니다.


우선 스핑크스 검색엔진은 C++ 로 만들어져 웬만한 OS에는 다 실행파일로
다운받아 돌려볼 수 있습니다만, docker 로 돌려봅니다.


우선 docker로 돌리기 전에 데이터를 준비해 보았습니다. 전문 검색을 위해서는 검색을 위한 FULL TEXT 자료가
필요한데 영문 사전을 찾아보았습니다.

위의 사이트에서 csv를 다운로드 받았습니다.

해당 데이터는 단어,품사,사전의미 의 세 컬럼으로 되어 있는 CSV 형식인데,
스핑크스에서는 첫 컬럼이 무조건 고유 doc id 가 지정되어 있어야 해서,
파이썬으로 간단히 해당 CSV를 읽어 첫 행에 1,2,3... 등의 순번을 넣어준 
CSV를 다시 만들었습니다. (첨부된 eng-dict.csv 참조)

이제는 docker-compose.yaml 에 다음의 내용을 추가해 봅니다.

  ##############################################################################
  # Store - Sphinx Search Engine
  ##############################################################################
  sphinx:
    image: macbre/sphinxsearch:3.4.1
    container_name: sphinx
    ports:
    - "36307:36307" # bind to local interface only!
    volumes:
    - ${PWD}/dhv/sphinx/data:/opt/sphinx/index  # directory where sphinx will store index data
    - ${PWD}/dhv/sphinx/sphinx.conf:/opt/sphinx/conf/sphinx.conf  # SphinxSE configuration file
    - ${PWD}/dhv/sphinx/eng-dict.csv:/tmp/eng-dict.csv:ro  # CSV Data
    mem_limit: 256m # match indexer.value from sphinx.conf

그 다음 ./dhv/sphinx 라는 폴더를 만들고 eng-dict.csv 를 옮기고, sphinx.conf 를 다음과 같은 내용을 만들어 줍니다.

source engdict
{
        type = csvpipe
        csvpipe_command = cat /tmp/eng-dict.csv
        csvpipe_field_string = word
        csvpipe_field_string = part
        csvpipe_field = meaning
}

index engdict_index
{
        source             = engdict
        path               = /opt/sphinx/index/engdict_index

        # @see http://sphinxsearch.com/docs/2.0.1/conf-blend-chars.html
        blend_chars                     = -

        # CALL SUGGEST
        min_infix_len                   = 3

        # wsparcie dla polskich znaków
        # @see http://sphinxsearch.com/wiki/doku.php?id=charset_tables#polish
        charset_table                   = 0..9, A..Z->a..z, a..z, U+0143->U+0144, U+0104->U+0105, U+0106->U+0107, U+0118->U+0119, U+0141->U+0142, U+00D3->U+00F3, U+015A->U+015B, U+0179->U+017A, U+017B->U+017C, U+0105, U+0107, U+0119, U+0142, U+00F3, U+015B, U+017A, U+017C, U+0144
}

indexer
{
        mem_limit          = 256M
}

searchd
{
        listen             = 36307:mysql41
        log                = /opt/sphinx/log/searchd.log
        query_log          = /opt/sphinx/log/query.log
        query_log_format   = sphinxql
        pid_file           = /opt/sphinx/searchd.pid

        # binlogs
        binlog_path = # disable logging
        # workers             = threads
}

만약 한글과 같은 CJK 문자를 이용할 거라면, charset_table 을 다음과 같이 해 줘야 한다는 군요.

U+FF01..U+FF5E->U+0021..U+007E, U+0021..U+0040, U+0041..U+005A->U+0061..U+007A, U+0061..U+007A, U+005B..U+0060, U+007B..U+007E

출처: https://crystalcube.co.kr/167 [유리상자 속 이야기]

위에 source 에서 csvpipe 를 지정했지만, 일반적인 경우에는 mysql의 특정 테이블을 지정해도 되더군요.

id 는 기본적으로 있는 것이고, word(단어), part(품사)는 실제 색인되지 않고 나중에 검색시 select 할 수 있는
컬럼으로 지정하기 위하여 csvpipe_field_string 라고 주었고, meaning(단어의미)는 실제 전문 검색용
색인을 위해서 csvpipe_field 라 지정하였습니다.

이제 해당 자료를 전문 검색을 위한 색인작업을 우선 해 주어야 합니다.

해당 작업은, 다음과 같은 docker-compose run 명령을 내리면 됩니다.

docker-compose run sphinx indexer --config /opt/sphinx/conf/sphinx.conf --all

그러면 아래와 같은 결과 나오며 색인이 잘 되었음을 볼 수 있습니다.
Creating docker-compose_sphinx_run ... done
Sphinx 3.4.1 (commit efbcc658)
Copyright (c) 2001-2021, Andrew Aksyonoff
Copyright (c) 2008-2016, Sphinx Technologies Inc (http://sphinxsearch.com)

using config file '/opt/sphinx/conf/sphinx.conf'...
indexing index 'engdict_index'...
collected 54555 docs, 4.2 MB
sorted 0.8 Mhits, 100.0% done
total 54555 docs, 4.182 Mb
total 0.4 sec, 11.84 Mb/sec, 154488 docs/sec

만약 검색 서비스를 하고 있었고 데이터가 수정되어 재색인이 필요하다면,
--rotate 옵션을 더 추가해 줍니다.

이제는 

docker-compose up 을 정상적으로 돌리는데,
그러면 해당 스핑크스 컨테이너는 searchd 검색 서비스가 작동합니다.

여기까지 해 놓으면 검색할 준비는 다 된 상태이고,
일반 mysql client를 이용하여 검색을 할 수 있습니다.

다음은 간단한 파이썬 테스트 스크립트 입니다.

import pymysql
db = pymysql.connect(host='192.168.35.241',port=36307,user='',passwd='',charset='utf8',db='')
cur = db.cursor()
sphinx_qry = 'apple | pear'
qry = f'SELECT id, word, part from engdict_index WHERE MATCH(\'{sphinx_qry}\') limit 20;'
cur.execute(qry)
row = cur.fetchall()
print(row)
cur.close();db.close()

그러면 결과는 tuple row의 tuple 목록으로 결과가 잘 나옵니다.


어느 분께는 도움이 되셨기를 ..

[Python] pyinstaller 로 만든 exe파일 Anti-Virus 오탐 문제 해결

파이썬으로 만든 코드를 EXE 로 만드는데 pyinstaller 를 애용합니다.(물론 동일한 것을 py2exe로 변환하면 다른 결과가 나오기도 합니다)처음에는 코드 사이닝 문제인가 싶기도 했지만, 그것은 아니었고virustotal.com 에 exe 파일을 올려 검사를 해 보았습니다.그 결과 다음의 바이러스토탈 사이트에서,총 68개의 바이러스 검출 엔진 ... » 내용보기

[Guacamole] 를 이용한 브라우저에서 RDP, VNC, SSH 통합관리하기

M1 MacBook Air를 사용하고나서 부터는 패러렐즈와 같은 VM 대신ESXi 서버를 따로 꾸며서 작업환경으로 이용하고 있습니다.문제는 윈도우, 리눅스, 맥 등의 연결하여 작업할 환경이원격 데스크탑 (RPD), 화면 공유 (VNC), 터미널 연결 (SSH) 등으로각각 다를 뿐더러 외부에서 접속을 하려면 해당 연결을 위하여개별 포트 포워딩을 해 줘야 ... » 내용보기

httpie curl 로 file upload 해 보기

파이썬으로 curl 과 같은 유틸리티 작업을 하려면 httpie 라는 것을 이용합니다.그런데 httpie를 이용하여 파일을 업로드하고 싶을 때 어떻게 하는지 살펴보겠습니다.우선 파일 업로드를 위한 웹서버를 찾아보았는데 적당한 것을 찾을 수 없었습니다.그래서 파이썬 샘플 업로드용 모듈이 있나 찾아보았더니 역시 uploadserver 라고 있었습니다.테스트... » 내용보기

[Photon OS] ssfhs 로 MAC 파일 마운트 하기

집에 별도 공유 시스템을 꾸미는데 기존 가지고 있던 2019 MacBookPro 를 공유 폴더를 관리하도록 했습니다.맥의 자체 기능 중 파일공유를 하고 samba 공유도 하도록 해 놓았습니다.수년 이상 이런 방식으로 파일을 공유하고, 이를 다른 윈도우 VM이나 Linux VM에서 공유 폴더를 소스 등으로 잘 이용하여 왔었습니다.이 SMB 방식은... » 내용보기

구글애드텍스트