12.9.2 불리안 전문 검색
MySQL은 IN BOOLEAN MODE
수식을 사용하여 불리 안 전문 검색을 실행할 수 있습니다. 이 수정자를 사용하면 검색 문자열의 시작이나 끝에 특정 문자가 특별한 의미를 갖습니다. 다음 쿼리는 +
및 -
연산자는 일치가 발생하는 단어가 존재해야한다와 단어가 존재해서는 안된다을 뜻합니다. 따라서이 쿼리는 "MySQL"이라는 단어는 포함되지만 "YourSQL"라는 단어는 포함되지 않은 모든 행이 검색됩니다.
mysql>SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+ | id | title | body | +----+-----------------------+-------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 2 | How To Use MySQL Well | After you went through a ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | | 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | | 6 | MySQL Security | When configured properly, MySQL ... | +----+-----------------------+-------------------------------------+
이 기능을 구현하면 MySQL에서는 암시 적 boolean 논리라고도 다음과 같은 것이 사용됩니다.
+
는AND
를 나타냅니다-
는NOT
을 나타냅니다[연산자 없음 암시 적으로
OR
을 나타냅니다
불리 안 전문 검색에는 다음과 같은 특징이 있습니다.
행은 자동으로 관련성 내림차순으로 정렬되지 않습니다.
InnoDB
테이블에서 boolean 쿼리를 실행하려면MATCH()
식의 모든 컬럼에FULLTEXT
인덱스가 필요합니다.MyISAM
검색 인덱스에 대한 boolean 쿼리는FULLTEXT
인덱스없이 작동합니다. 그러나이 방법으로 실행되는 검색의 속도는 매우 느립니다.단어의 최소 길이와 최대 길이 전문 파라미터는
InnoDB
검색 인덱스의 경우innodb_ft_min_token_size
및innodb_ft_max_token_size
,MyISAM
검색 인덱스의 경우는ft_min_word_len
및ft_max_word_len
에 적용됩니다.중지 단어 목록이 적용됩니다. 이들은
InnoDB
검색 인덱스의 경우innodb_ft_enable_stopword
,innodb_ft_server_stopword_table
및innodb_ft_user_stopword_table
,MyISAM
검색 인덱스의 경우ft_stopword_file
의해 제어됩니다.InnoDB
의 전체 텍스트 검색은'++apple'
의 예와 마찬가지로 하나의 검색 단어에 여러 연산자를 사용하도록 지원되지 않습니다. MyISAM 전문 검색에서는 동일한 검색이 제대로 처리되고 검색 단어에 인접 연산자를 제외한 모든 연산자가 무시됩니다.InnoDB
의 전체 텍스트 검색에서는 선두의 더하기 기호 또는 빼기 만 지원되고 있습니다. 예를 들어,InnoDB
는'+apple'
이 지원되지만,'apple+'
는 지원되지 않습니다. 끝에 더하기 기호 또는 빼기 기호를 지정하면InnoDB
에서 구문 오류가보고됩니다.InnoDB
의 전체 텍스트 검색에서 와일드 카드 ('+*'
)를 사용한 첫 번째 더하기 더하기와 빼기 기호의 조합 ('+-'
) 또는 선두의 플러스 기호와 마이너스 기호의 조합 ('+-apple'
)는 지원되지 않습니다. 이러한 잘못된 쿼리 구문 오류가 반환됩니다.MyISAM
검색 인덱스에 적용되는 50 %의 임계 값은 사용되지 않습니다.
불리 안 전문 검색 기능은 다음 연산자가 지원됩니다.
+
선행 또는 후행 더하기 기호는이 단어가 반환되는 각 행에 존재해야한다는 것을 나타냅니다.
InnoDB
는 선두의 플러스 기호 만 지원되고 있습니다.-
선행 또는 후행 빼기 기호는이 단어가 반환되는 행의 어느 것에도 존재해서는 안되는 것을 나타냅니다.
InnoDB
는 첫 번째 빼기 만 지원되고 있습니다.참고 :
-
연산자는 본래라면 다른 검색어로 일치 시키 행을 제외 할 경우에만 사용합니다. 따라서-
앞에있는 검색어 만 포함 boolean 모드의 검색에서는 빈 결과가 반환됩니다. "제외 된 검색 단어 중 하나를 포함하는 행을 제외한 모든 행"이 반환되는 것은 아닙니다.(연산자 없음)
기본적으로 (
+
와-
가 모두 지정되지 않은 경우)이 단어는 옵션이지만, 그것을 포함한 행의 평가는 높아집니다. 이것은IN BOOLEAN MODE
규정되지MATCH() ... AGAINST()
의 동작과 비슷합니다.@
distance
이 연산자는
InnoDB
테이블에서만 작동합니다. 2 개 이상의 단어가 모두 서로 지정된 거리에서 시작하는지 여부가 단어 단위로 테스트됩니다.@
연산자 직전에 큰 따옴표로 둘러싸인 문자열의 검색 단어를 지정합니다 (예를 들어,distance
MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE)
).> <
이 두 연산자는 행에 할당 된 관련 값에 단어 공헌도를 변경하는 데 사용됩니다.
>
연산자는 공헌도를 올리고<
연산자는 공헌도를 낮 춥니 다. 다음 목록 다음에 예제를 참조하십시오.()
괄호는 단어를 부분 식에 그룹화합니다. 괄호로 둘러싸인 그룹은 중첩 될 수 있습니다.
~
첫 번째 물결은 부정 연산자로서 기능하기 위해서 행의 관련성에 단어 기여도가 마이너스가됩니다. 이것은 "노이즈"단어에 마크를 넣을 때 편리합니다. 이러한 단어를 포함하는 행은 기타보다 낮게 평가되지만,
-
연산자를 사용한 경우처럼 완전히 제외 될 수는 없습니다.*
별표 잘린 (또는 와일드 카드) 연산자로 작동합니다. 다른 연산자와 달리 영향을받는 단어에 추가됩니다.
*
연산자 앞의 단어로 시작되면 단어가 일치합니다.잘라 연산자를 붙여 단어가 지정되어있는 경우에는 그 단어가 너무 짧거나 중지 단어이거나해도 boolean 쿼리에서 제거되지 않습니다. 단어가 너무 짧은 여부는
InnoDB
테이블의 경우innodb_ft_min_token_size
설정MyISAM
테이블의 경우ft_min_word_len
에 의해 결정됩니다. 와일드 카드 단어가 하나 이상의 단어의 처음으로 존재해야한다 프리픽스로 간주됩니다. 단어의 최소 길이가 4 인 경우는'+
를 찾기 위해 두 번째 쿼리에서 너무 짧은 검색어word
+the*'the
무시되므로'+
의 검색보다 적은 행 이 반환 될 수 있습니다.word
+the'"
큰 따옴표 ( "
"
") 문자에 둘러싸인 문구는 입력 된 그대로 문구가 포함 된 행에만 일치합니다. 전체 엔진에서는 문구가 여러 단어로 분리되고 그 낱말의FULLTEXT
인덱스 내에서 검색이 실행됩니다. 단어 이외의 문자는 정확히 일치해야합니다. 구문 검색에서는 그 문구와 똑같은 단어가 순서대로 일치에 포함되는 것만이 필요합니다. 예를 들어,"test phrase"
는"test, phrase"
와 일치합니다.문구 인덱스에있는 단어가 포함되지 않는 경우는 결과가 비어 있습니다. 단어가 텍스트에 존재하지 않는 경우, 중지 단어 인 경우, 또는 인덱싱 된 단어의 최소 길이보다 짧은 경우의 조합으로 인해 단어가 인덱스에 존재하지 않을 수 있습니다.
다음 예제에서는 boolean 전문 연산자를 사용하는 일부 검색 문자열을 시연합니다.
'apple banana'
두 단어 중 하나 이상을 포함하는 행을 검색합니다.
+ apple + juice '
두 단어가 포함 된 행을 검색합니다.
+ apple macintosh '
단어 "apple"이 포함 된 행을 검색되지만 행에 "macintosh"도 포함 된 경우 행을 높게 평가됩니다.
+ apple -macintosh '
단어 "apple"을 포함하지만, "macintosh"은 포함하지 않는 행을 검색합니다.
+ apple ~ macintosh '
단어 "apple"이 포함 된 행을 검색하지만 줄에 단어 "macintosh"도 포함되는 경우는 행에 포함되지 않는 경우보다 낮게 평가됩니다. 이것은 "macintosh"가 존재하면 행이 전혀 반환하지
'+apple -macintosh'
의 검색보다 "소프트"입니다.+ apple + (> turnover <strudel) '
단어 "apple"과 "turnover"또는 "apple"과 "strudel"(순서 불문)를 포함하는 행을 찾지 만 "apple turnover"을 "apple strudel '보다 높게 평가합니다.
'apple *'
"apple", "apples", "applesauce ','applet '등의 단어가 포함 된 행을 검색합니다.
' "some words"'
"some words '와 똑같은 문구가 포함 된 행을 검색합니다 (예 :"some words of wisdom "를 포함하는 행이 검색되지만"some noise words "는 찾지 않습니다).
참고문구를 둘러싸고 "
"
"문자는 문구를 구분 연산자 문자입니다. 검색 문자열 자체 주위에 따옴표가 없습니다.
InnoDB boolean 모드 검색의 관련성 순위
InnoDB
의 전체 텍스트 검색은 Sphinx 전문 검색 엔진을 모델로 사용되는 알고리즘은 BM25 및 TF-IDF 순위 알고리즘을 기반으로합니다. 이러한 이유 때문에 InnoDB
의 불리 안 전문 검색의 관련성 순위는 MyISAM
의 관련성 순위와 다를 수 있습니다.
InnoDB
는 "term frequency-inverse document frequency"( TF-IDF
) 가중치 시스템의 편차를 사용하여 지정된 전체 텍스트 검색 쿼리 문서의 관련성에 순위가 매겨집니다. TF-IDF
가중치는 문서에서 단어가 출현하는 빈도에 따라 컬렉션의 모든 문서에서 단어가 출현하는 빈도에 따라 오프셋됩니다. 즉, 단어가 문서에서 출현하는 빈도가 높아질수록 그 단어가 문서 컬렉션에서 출현하는 빈도가 낮아지고, 문서의 순위가 높아집니다.
관련성 순위 계산 방법
단어의 출현 빈도 ( TF
) 값은 단어가 문서에 나타나는 횟수입니다. 단어의 역 문서 빈도 ( IDF
) 값은 다음 공식을 사용하여 계산됩니다. 여기에서 total_records
는 컬렉션의 레코드 수 matching_records
는 검색어가 표시되는 레코드 수입니다.
$ {IDF} = log10 ($ {total_records} / $ {matching_records})
문서에 단어가 여러 번 포함되는 경우는 IDF 값이 TF 값을 곱합니다.
$ {TF} * $ {IDF}
TF
와 IDF
값을 사용하는 경우 문서의 관련성 순위가 다음 공식을 사용하여 계산됩니다.
$ {rank} = $ {TF} * $ {IDF} * $ {IDF}
공식은 다음 예제에서 시연되고 있습니다.
단일 단어 검색의 관련성 순위
이 예에서는 단일 단어 검색의 관련성 순위 계산을 시연합니다.
mysql> CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) ) ENGINE=InnoDB; Query OK, 0 rows affected (1.04 sec) mysql> INSERT INTO articles (title,body) VALUES ('MySQL Tutorial','This database tutorial ...'), ("How To Use MySQL",'After you went through a ...'), ('Optimizing Your Database','In this database tutorial ...'), ('MySQL vs. YourSQL','When comparing databases ...'), ('MySQL Security','When configured properly, MySQL ...'), ('Database, Database, Database','database database database'), ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), ('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..'); Query OK, 8 rows affected (0.06 sec) Records: 8 Duplicates: 0 Warnings: 0 mysql> SELECT id, title, body, MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) AS score FROM articles ORDER BY score DESC; +----+------------------------------+-------------------------------------+---------------------+ | id | title | body | score | +----+------------------------------+-------------------------------------+---------------------+ | 6 | Database, Database, Database | database database database | 1.0886961221694946 | | 3 | Optimizing Your Database | In this database tutorial ... | 0.36289870738983154 | | 1 | MySQL Tutorial | This database tutorial ... | 0.18144935369491577 | | 2 | How To Use MySQL | After you went through a ... | 0 | | 4 | MySQL vs. YourSQL | When comparing databases ... | 0 | | 5 | MySQL Security | When configured properly, MySQL ... | 0 | | 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0 | | 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0 | +----+------------------------------+-------------------------------------+---------------------+ 8 rows in set (0.00 sec)
총 8 개의 레코드가 있으며이 중 3 개가 "database"라는 검색어와 일치합니다. 첫 번째 레코드 ( id 6
)에는 검색어가 6 회 들어 관련성 순위는 1.0886961221694946
입니다. 이 순위 값은 6 TF
값 (레코드 id 6
에는 "database"라는 검색어가 6 회 출현합니다) 및 다음과 같이 계산된다 0.42596873216370745의 IDF
값 (여기서 8은 총 레코드 숫자 3은 검색어가 출현하는 레코드 수)를 사용하여 계산됩니다.
$ {IDF} = log10 (8 / 3) = 0.42596873216370745
그 후, TF
와 IDF
값 순위 공식적으로 입력됩니다.
$ {rank} = $ {TF} * $ {IDF} * $ {IDF}
MySQL 명령 행 클라이언트에서 계산을 수행하면 1.088696164686938 순위 값이 반환됩니다.
mysql> SELECT 6*log10(8/3)*log10(8/3); +-------------------------+ | 6*log10(8/3)*log10(8/3) | +-------------------------+ | 1.088696164686938 | +-------------------------+ 1 row in set (0.00 sec)
SELECT ... MATCH ... AGAINST
문과 MySQL 명령 행 클라이언트로 반환되는 순위 값 ( 1.0886961221694946
과 1.088696164686938
)에 약간의 차이가있을 수 있습니다. 이 차이는 정수와 부동 소수점 / 배정도 간의 캐스트 (관련 정확성 및 둥근 결정과 함께) InnoDB
가 내부적으로 수행되는 방법 및 기타 장소 (MySQL 명령 행 클라이언트 및 기타 유형의 계산기 등 )에서 실행되는 방식 때문에 발생합니다.
여러 단어 검색의 관련성 순위
이 예에서는 이전 예에서 사용 된 articles
테이블 및 데이터를 기반으로 여러 단어의 전체 텍스트 검색의 관련성 순위 계산을 시연합니다.
복수의 단어로 검색하는 경우는 다음의 공식으로 같이 관련성 순위 값이 각 단어의 관련성 순위 합계입니다.
$ {rank} = $ {TF} * $ {IDF} * $ {IDF} + $ {TF} * $ {IDF} * $ {IDF}
두 단어 ( 'mysql tutorial')에서 검색을 실행하면 다음과 같은 결과가 반환됩니다.
mysql> SELECT id, title, body, MATCH (title,body) AGAINST ('mysql tutorial' IN BOOLEAN MODE) AS score FROM articles ORDER BY score DESC; +----+------------------------------+-------------------------------------+----------------------+ | id | title | body | score | +----+------------------------------+-------------------------------------+----------------------+ | 1 | MySQL Tutorial | This database tutorial ... | 0.7405621409416199 | | 3 | Optimizing Your Database | In this database tutorial ... | 0.3624762296676636 | | 5 | MySQL Security | When configured properly, MySQL ... | 0.031219376251101494 | | 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0.031219376251101494 | | 2 | How To Use MySQL | After you went through a ... | 0.015609688125550747 | | 4 | MySQL vs. YourSQL | When comparing databases ... | 0.015609688125550747 | | 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 | | 6 | Database, Database, Database | database database database | 0 | +----+------------------------------+-------------------------------------+----------------------+ 8 rows in set (0.00 sec)
첫 번째 레코드 ( id 8
)는 'mysql'가 1 회 출현하고 'tutorial'가 2 회 출현합니다. 'mysql'에 일치하는 레코드는 6 개의 'tutorial'에 일치하는 레코드가 2 개 있습니다. MySQL 명령 행 클라이언트에서는 이러한 값을 여러 단어 검색 순위 공식적으로 삽입 할 때 예상되는 순위 값이 반환됩니다.
mysql> SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)); +-------------------------------------------------------+ | (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) | +-------------------------------------------------------+ | 0.7405621541938003 | +-------------------------------------------------------+ 1 row in set (0.00 sec)
위의 예에서는 SELECT ... MATCH ... AGAINST
문과 MySQL 명령 행 클라이언트로 반환되는 순위 값에 약간의 차이가 있음을 설명했습니다.