home..

Postgresql documentation 살펴보기 - Text Search

Introduction

Text Search는 쿼리와 연관되는 자연어로 구성된 documents를 탐색하는 기능이다. 보통 쿼리에서 찾는 용어를 포함하는 모든 문서를 찾아 쿼리와 유사한 순서대로 추출한다. 간단하게 보면 쿼리는 단어들의 묶음이고 유사도는 문서에서 단어의 빈도를 의미한다.

정규표현식의 LIKE 등 Text Search는 이미 기존에 있었지만 몇 가지 중요한 부분이 빠져있었다.

Full Text indexing은 문서를 전처리하여 이후의 searching에서 index가 활용된다. 전처리는 아래와 같다.

SELECT title || ' ' || author || ' ' || abstract || ' ' || body AS document 
FROM messages
WHERE mid = 12;

SELECT m.title || ' ' || m.author || ' ' || m.abstract || ' ' || d.body AS document 
FROM messages m, docs d
WHERE m.mid = d.did AND m.mid = 12;

text 검색을 위해서는 모든 문서는 전처리된 tsvector형식이어야 한다.

Basic Text Matching

Full Text Searching은 match 연산자인 @@를 기반으로 한다. @@tsvector(document)가 tsquery(query)와 일치하면 t(true)를 반환한다.

SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;
/*
 ?column?
----------
 t
 */
SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector;
/*
 ?column?
----------
 t
 */

tsquery는 검색하려는 용어(normalized 단어로 AND(&), OR(|), NOT(!), FOLLOWED BY(<->) 연산자 사용 가능)를 포함한다. to_tsquery는 쿼리에서 단어를 normalize를 적용해주고 to_tsvector는 문서의 parse 및 normalize를 도와준다.

SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');
/*
 ?column? 
----------
 t
 */
-- 아래는 wrong example
SELECT 'fat cats ate fat rats'::tsvector @@ to_tsquery('fat & rat');
/*
 ?column? 
----------
 f
*/

tsquery<->( FOLLOWED BY )는 앞 문자 뒤에 뒤 문자가 오는지를 확인한다.

SELECT to_tsvector('fatal error') @@ to_tsquery('fatal <-> error');
/*
 ?column? 
----------
 t
*/
SELECT to_tsvector('error is not fatal') @@ to_tsquery('fatal <-> error');
/*
 ?column? 
----------
 f
*/

phraseto_tsquerystop words를 고려하여 <->( FOLLOWED BY ) 포함하여 변환해준다.

SELECT phraseto_tsquery('cats ate rats');
/*
       phraseto_tsquery        
-------------------------------
 'cat' <-> 'ate' <-> 'rat'
*/
SELECT phraseto_tsquery('the cats ate the rats');
/*
       phraseto_tsquery        
-------------------------------
 'cat' <-> 'ate' <2> 'rat'
 */

Tables and Indexes

Searching a Table

index없이 text 검색이 가능하다.

body field에 friend가 있으면 title field를 출력하는 쿼리는 아래와 같다.

SELECT title
FROM pgweb
WHERE to_tsvector('english'. body) @@ to_tsquery('english', 'frield');

여기서는 friends, friendly등 연관된 단어도 찾아준다. configuration 변수('english') 는 생략 가능하다.

Creating Indexes

GIN Index를 생성하면 검색 속도를 높일 수 있다.

CREATE INDEX pgweb_idx ON pgweb USING GIN(to_tsvector('english', body));

configuration 이름을 명시하는 text 검색 함수가 indexes 생성에 이용될 수 있다. 이는 index는 default_text_search_config(https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DEFAULT-TEXT-SEARCH-CONFIG)에 영향을 받으면 안되기 때문이다. 서로 다른 text search configuration으로 생성된 tsvector가 포함된 내용은 index가 일관적이지 않아 부정확해질 수 있다.

즉, WHERE to_tsvector('english', body) @@ 'a & b'는 되지만 WHERE to_tsvector(body) @@ 'a & b'는 index를 생성할 수 없다.

configuration 이름을 테이블의 칼럼으로도 사용 가능하다.

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(config_name, body));

위에서 config namepgweb의 칼럼으로 문서가 서로 다른 언어를 포함한 경우 유용하게 쓰일 수 있다.

또한 칼럼을 concat해서 indexes로 생성할 수 있다.

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', title || ' ' || body));
© 2024 Yujin Lee   •  Powered by Soopr   •  Theme  Moonwalk