2015년 8월 28일 금요일

Elasticsearch를 사용하여 게시판의 첨부파일 내용 검색하기

이번에는 홈페이지 또는 기업에서 많이 사용되는 게시판의 제목과 본문 그리고 첨부된 문서의 텍스트를 검색하는 단계를 정리한다.


  • Elasticsearch 버전 1.7.1
  • Elastic search mapper attachment 버전 2.7.0

1. 필요한 플러그인 설치

Mapper Attachments Type for Elasticsearch

pdf 또는 ms-office 문서에서 텍스트 추출을 하기 위한 플러그인
문서파일은 아파치 Tika가 동작해서 attachment 유형을 사용할 수있게 해준다.

bin/plugin -install elasticsearch/elasticsearch-mapper-attachments/2.7.0

설치확인
curl  -XGET  http://localhost:9200/_nodes?pretty

2. 인덱스 매핑 정의

인덱스 매핑은 한국어 형태소분석을 사용하도록 설정한다.
설치 참고) Elasticsearch에 한국어 형태소분석기 Mecab ko 적용

PUT /test
{
"settings" : {
    "index":{
      "analysis":{
        "filter" : {
            "synonym" : {
                "type" : "synonym",
                "synonyms_path" : "analysis/synonyms.txt"
            }
        },
        "analyzer":{
          "korean":{
            "filter" : [
              "standard",
              "lowercase",
              "stop",
              "synonym"
            ],
            "type":"custom",
            "tokenizer":"mecab_ko_standard_tokenizer"
          }
        },
        "tokenizer": {
          "mecab_ko_standard_tokenizer": {
            "type": "mecab_ko_standard_tokenizer",
            "mecab_args": "-d /home/elasticsearch/knowledge/mecab/dic/mecab-ko-dic"
          }
        }
      }
    }
 },
"mappings": {
    "board" : {
      "properties": {
        "title": {
          "type": "string",
          "analyzer": "korean"
        },
        "content": {
          "type": "string",
          "analyzer": "korean"
        },
          "file": {
          "type": "attachment",
          "fields" : { "file" : { "term_vector":"with_positions_offsets", "store":"yes” } },
          "analyzer": "korean"
        }
      }
    }
  }
}

3. JDBC River를 사용해서 DB데이터 id, title, content, filePath, filterYn, createDate를 색인

JDBC River 사용하기

수동 입력의 예)
POST /test/board/1
{
 "id": "1",
 "title" : “「2015~2016년 해외 한국자료실 설치 지원 사업」수요조사 신청 안내",
 "content" : "대한민국 국립중앙도서관에서는 「2015~2016 해외 한국자료실 설치 지원 사업 : Window On Korea(WOK)」을 위한 수요조사를 실시하오니, 관심 있는 기관들의 많은 참여 바랍니다. 한국자료실 설치를 희망하는 기관은 “수요조사 신청서“를 작성하여, e-mail 또는 fax로 제출하여 주시기 바랍니다. ㅇ 2015년도 설치사업 : 2015년 5월 15일(금)까지  ㅇ 2016년도 설치사업 : 2015년 10월 30일(금)까지",
 "filePath": "/data1/attach/doc/1.docx",
 "file": "",
 "filterYn": "N",
 "createDate": "2015-08-28T12:00:00"
}

4. 첨부파일이 저장되어 있는 서버에서 Elasticsearch로 첨부파일 색인 요청을 한다.


문서파일 업데이트 데몬을 통해 해당 Index의 문서중에 filterYn값이 N인 파일을 BASE64인코딩해서 업데이트한다.

문서파일 색인 업데이트 프로세스

4.1 filterYn에서 N인 조건 + filePath가 empty가 아닌 문서 가져오기
검색조건
GET /test/board/_search
{
  "fields": ["id", "filePath"]
  ,"query": {
    "filtered": {
      "filter":
      {
        "bool": {
          "must": {"term": { "filterYn": “n" }},
          "must_not": {"term": {"filePath": ""}}
        }
      }
    }
  }
}

4.2 문서결과는 id와 filePath만 전달 받는다.
{
   "took": 14,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "test",
            "_type": "board",
            "_id": "1",
            "_score": 1,
            "fields": {
               "id": [
                  "1"
               ],
               "filePath": [
                  "/data1/attach/doc/1.docx"
               ]
            }
         }
      ]
   }
}

4.3 filePath 필드의 문서는 바이너리 데이터를 BASE64로 인코딩한다.
   - 바이너리 파일을 읽어서 BASE64로 반환하는 JAVA Class
     https://gist.github.com/utkarsh2012/1276960

4.4 Elasticsearch에 문서를 업데이트 요청한다. 데몬에서 Elasticsearch로 전달하는 URL
CURL로 업데이트할 경우의 예)
curl -XPOST  “localhost:9200/test/board/1/_update" -d '
{
   “doc” :
    {
         “id”: “1”,
         “filterYn”: “Y”,
         “file” : “ base64 encoding string …."
    }
}

5. 검색 결과 확인하기


GET /test/board/_search
{
  "fields": ["id", "title", "content"]
  ,"query": {
    "bool": {
         "must": [
           {
             "multi_match": {
               "query": “설치사업",
               "fields": [
                 "content^10",
                 "title^100",
                 "file"
                 ],
              "type": "cross_fields",
              "operator":"AND",
              "minimum_should_match": "75%"
             }
           }
         ]
       }
  },
  "highlight": {
    "fields": {"file": {"fragment_size" : 150, "number_of_fragments" : 3}}
  }
}

댓글 없음:

댓글 쓰기