Solr는 단독 애플리케이션 서버 형태로 작동하며, REST 형식의 API를 제공한다. 문서들은 HTTP를 이용해서 XML, JSON, CSV 혹은 바이너리 형태등으로 색인요청을 할 수 있다. 검색 역시 HTTP GET 으로 요청하며, 검색결과는 XML, JSON, CSV, 바이너리 형태로 가져올 수 있다.
Full-text search
높은 웹 트래픽을 감당할 수 있도록 최적화.
XML, JSON과 HTTP등의 표준 오픈 인터페이스를 제공.
HTML 기반의 관리자 인터페이스
Linearly scalable, auto index replication, 자동 failover와 복구
대부분의 CMS 툴들이 그렇듯이 (joinc의 CMS인)모니위키 역시 검색기능이라고 할 만한게 없다. Full text search기능이 있긴 하지만 grep을 이용한 건데, 그냥 쓰지 않는게 낫다.
하여 구글 custom search를 도입했다. 2007년 부터 2011년까지 custom search(이하 CS)를 이용해서 검색서비스를 제공했는데, 쓸만했지만 몇 가지 문제가 있었다.
색인 갱신 주기를 조절할 수 없다. 컨텐츠를 옮기거나 하는 등으로 URL이 변경되면, 다음번 색인 까지 한참 동안 링크가 깨진다. : 실시간 색인을 포기해야 한다는 의미다.
URL 맵이 엉망으로 만들어진다. 구글 CS는 웹 크롤러를 이용해서 문서를 수집한다. 모든 가능한 링크에 대해서 색인이 만들어 지는데, 그러다 보니 ?action=diff 등과 같은 wiki 액션 페이지들도 색인을 한다. memset 페이지 뿐만 아니라 memset??action=diff 와 같은 페이지까지 색인한다. 쓸데없는 문서들까지 recall 된다는 이야기다.
텍스트 브라우저로 브라우징 할 수 없다. 주로 w3m을 이용해서 브라우징을 한다. 구글 CS는 Ajax 호출이기 때문에 w3m에서는 검색결과를 볼 수 없다. 대부분의 사람들에게는 상관없겠지만 w3m을 이용해서 브라우징하고 컨텐츠를 작성하는 나에게는 중요한 문제다.
문제를 해결하기 위해서는 컨텐츠 기반으로 색인을 하면 되는데, lucene이 거의 유일한 해결책이라 할 수 있겠다. 하지만 lucene는 너무 무겁고, 설치/운용이 귀찮다. 직접 만드는 건 더 귀찮다. (Mysql도 full text search를 제공한다고 하긴하더라.)
이래 저래 귀찮아서 그냥 CS를 사용하고 있었는데, chef를 가지고 놀다가 우연찮게 solr를 발견했다. chef에서는 메타 정보 검색을 위해서 solr를 사용 한다. 이게 뭔가 하고 살펴봤더니 루신기반의 검색 소프트웨어란다. 게다가 설치/운용도 간단하더라. 이후 검색서비스를 solr로 대체해서 지금까지 사용하고 있다.
2007년 처음 solr를 적용했을 때 버전이 3.x 였는데, 어느덧 2014년 지금은 4.7이다. solr 4.7을 설치하고 운용하는 방법을 정리하려고 한다.
http://lucene.apache.org/solr 에서 다운로드 했다. ()현재 최신 버전은 4.7.0이다.
다운로드한 solr 소프트웨어는 solr server 1에 설치했다. 분산 검색전에 단일 호스트에서의 검색부터 끝내야 하지 않겠는가. 단일 호스트 검색을 끝낸 후 분산 검색을 수행한다. 나는 /opt/solr 디렉토리에 설치했다.
웹 브라우저로 http://192.168.56.5:8983/solr에 접근하면, Solr 대쉬보드 화면을 볼 수 있다.
https://lh6.googleusercontent.com/-OvGe99HqSqg/UyXVxWqf0yI/AAAAAAAADfI/cc9GjYqXOdg/s640/solr01.png
예쁘다.
Joinc 컨텐츠를 색인하기 전에 solr에서 tutorial 용으로 제공하는 example 문서를 색인해보기로 했다. solr는 실행시간에 컨텐츠 색인의 추가/업데이트/삭제가 가능하다. XML, JSON, CSV 등 다양한 형식으로 컨텐츠를 색인할 수 있다.
exampledocs 디렉토리에 샘플파일이 있는데, 이 파일을 색인해 보기로 했다. exampledocs 디렉토리 밑에는 컨텐츠를 색인하고 업데이트 할 수 있는 자바 프로그램인 post.jar가 있다. post.jar를 이용해서 solr.xml과 monitor.xml을 색인했다.
1
2
3
4
5
6
7
8
9
# cd /opt/solr/example/exampledocs
# java -jar post.jar solr.xml monitor.xml
SimplePostTool version 1.5
Posting files to base url http://localhost:8983/solr/update using content-type application/xml..
POSTing file solr.xml
POSTing file monitor.xml
2 files indexed.
COMMITting Solr index changes to http://localhost:8983/solr/update..
두개의 문서가 색인됐다. 색인 정보는 solr 관리자 페이지의 Core Admin 탭에서 확인할 수 있다.
https://lh4.googleusercontent.com/-EqeZ4Q3kSNI/UyhssLbj64I/AAAAAAAADfg/z08TvRqI-jo/s640/solr02.png
관리자 페이지에서 검색결과도 확인할 수 있다. collection탭에서 테스트할 collection(지금은 collection1 하나만 있을거다)를 선택하면, Query메뉴가 있다. 클릭하면 질의어와 각종 검색 옵션을 설정할 수 있는 페이지가 뜬다. 질의어를 넣고 Execute Query버튼을 클릭하면, 검색결과를 확인할 수 있다. solr로 검색을 할 경우 http://192.168.56.5:8983/solr/collection1/select?q=solr&wt=json&indent=true 와 같은 요청이 생성된다.
https://lh6.googleusercontent.com/-1x305BQIi9o/Uyhv1gfDFJI/AAAAAAAADfs/pblXtjOUEWU/s640/solr03.png
exampledocs에 있는 다른 문서들도 색인해서 테스트를 해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# java -jar post.jar *.xml
SimplePostTool version 1.5
Posting files to base url http://localhost:8983/solr/update using content-type application/xml..
POSTing file gb18030-example.xml
POSTing file hd.xml
POSTing file ipod_other.xml
POSTing file ipod_video.xml
POSTing file manufacturers.xml
POSTing file mem.xml
POSTing file money.xml
POSTing file monitor2.xml
POSTing file monitor.xml
POSTing file mp500.xml
POSTing file sd500.xml
POSTing file solr.xml
POSTing file utf8-example.xml
POSTing file vidcard.xml
14 files indexed.
COMMITting Solr index changes to http://localhost:8983/solr/update..
이 문서대로 색인을 했다면 solr.xml 문서를 두번 색인했을 것이다. 하지만 "solr"로 검색하면 여전히 하나의 문서만 검색된다. 이유는 문서를 색인할 때 참고하는 schema.xml에 "uniqueKey"로 "id"필드를 설정했기 때문이다. uniqueKey로 설정된 필드는 단지 하나만 존재할 수 있기 때문에, 필드의 값이 같을 경우에는 추가되는 대신에 "업데이트"된다.
이제 다시 java -jar post.jar를 실행하더라도 (모든 문서가 중복되기 때문에) 색인정보는 변하지 않을 것이다.
검색은 HTTP GET을 이용하면 된다. query는 q파라메터의 값으로 넘긴다. 일단은 q 파라메터를 이용하는 것으로 검색이 가능하지만, 정교한 검색을 위해서 옵션 파라메터를 사용할 수 있다. 예컨데, fl 파라메터를 이용해서 검색 필드를 지정하거나 소트(sort) 필드의 지정, 출력 형식(XML, JSON)등을 지정할 수 있다.
q=video&fl=name,id : name과 id 필드에서 video를 검색한다.
q=video&fl=name,id,score : 문서의 가중치(score)를 출력한다.
q=video&fl=*,score : 모든 필드에서 video를 검색하고, 문서 가중치도 출력한다.
Solr은 모든 기능을 HTTP를 통해서 제공한다. 여기에는 색인, 검색, 삭제, 업데이트 뿐만 아니라 스키마추가/업데이트, 리플리케이션 등 모든 기능을 포함한다. 여기에서는 색인 추가,업데이트,삭제, 검색 등 필수 기능만 테스트한다.
Solr는 POST와 GET을 이용해서 색인을 관리하고 검색을 요청할 수 있다. HTTP 만으로 모든 작업을 할 수 있기 때문에, CURL등의 도구를 이용해서 간단하게 검색 애플리케이션을 개발할 수 있다. 나는 php에서 제공하는 CURL(client URL Library)를 이용해서 웹 애플리케이션을 개발했다.
CURL을 이용해서 Solr의 기능을 테스트 한다. exampledoc 디렉토리 밑에 보면 books.json이 있는데, 이 파일의 스키마로 테스트하기로 했다.
books.json 파일을 참고해서 테스트에 사용할 cosmos.json을 만들었다.
schema를 설계하기 위해서는 문서를 어떤 기준으로 나눌 것인지를 결정해야 한다. joinc의 컨텐츠는 moniwiki에서 관리하는데, 데이터베이스가 아닌 text로 저장된다. 데이터 형식은 html이 아닌 moniwiki의 고유 마크다운 형식을 따른다.
문서는 title과 body만 가지고 있다. 문서저자, 작성일과 같은 정보는 없다. 따라서 "title"과 "body" 단지 두 개의 필드로 구성한다.
id는 문서가 저장된 파일 이름으로 한다. 정리하자면 이렇다.
마크다운 형식의 joinc wiki 문서를 그대로 색인하기에는 문제가 있다. 유저가 웹 브라우저를 이용해서 보는 페이지의 내용 그대로 색인을 해야 한다. HTML 문서를 색인하기로 했다. 링크기반으로 웹 문서를 수집하는 삽질은 하지 않기로 했다. 어차피 원문을 내가 관리하고 있으니, 색인해야 할 URL의 목록은 간단히 만들 수 있다. 간단한 스크립트를 돌려서 URL 목록을 만든 후, w3m으로 URL을 읽어서 text 파일로 변환하기로 했다.
w3m으로 웹 문서를 txt로 저장하는 방법이다.
Contents
1. Solr
1.1. Solr의 기능들
1.1.1. Solr의 Lucene 확장 기능
2. Joinc 컨텐츠 검색 서비스 만들기
2.1. Joinc Solr 적용 방법
3. Solr Tutorial
3.1. 요구 사항
3.2. solr 다운로드 및 설치
3.2.1. solr server 실행
3.2.2. solr example 문서 색인
3.2.3. 색인 업데이트
3.2.4. 색인 삭제
3.3. 검색 Query
3.4. 하일라이팅
3.5. 내장 검색 UI
4. HTTP API
4.1. Update와 Insert
4.2. Search
4.3. delete
5. Joinc 검색 서비스 개발
5.1. schema 설계
5.2. 색인
5.3. 검색 인터페이스 개발
5.4. 검색 출력 페이지 개발
5.5. 분석기
6. 히스토리
7. 참고
1. Solr
1.1. Solr의 기능들
1.1.1. Solr의 Lucene 확장 기능
2. Joinc 컨텐츠 검색 서비스 만들기
2.1. Joinc Solr 적용 방법
3. Solr Tutorial
3.1. 요구 사항
3.2. solr 다운로드 및 설치
3.2.1. solr server 실행
3.2.2. solr example 문서 색인
3.2.3. 색인 업데이트
3.2.4. 색인 삭제
3.3. 검색 Query
3.4. 하일라이팅
3.5. 내장 검색 UI
4. HTTP API
4.1. Update와 Insert
4.2. Search
4.3. delete
5. Joinc 검색 서비스 개발
5.1. schema 설계
5.2. 색인
5.3. 검색 인터페이스 개발
5.4. 검색 출력 페이지 개발
5.5. 분석기
6. 히스토리
7. 참고
Recent Posts
Archive Posts
Tags