为了帮助大家了解布尔查询,这里摘录一段MySQL手册里的相关描述。如下:
1. 'applebanana'
寻找包含至少两个单词中的一个的行。
2. '+apple+juice'
寻找两个单词都包含的行。
3. '+applemacintosh'
寻找包含单词“apple”的行,若这些行也包含单词“macintosh”,则列为更高等级。
4. '+apple-macintosh'
寻找包含单词“apple”但不包含单词 “macintosh”的行。
5. '+apple+(>turnover
寻找包含单词“apple”和“turnover”的行,或包含“apple”和“strudel”的行 (无先后顺序),然而包含“apple turnover”的行较包含“apple strudel”的行排列等级更为高。
6. 'apple*'
寻找包含“apple”、“apples”、“applesauce”或“applet”的行。
7. '"somewords"'
寻找包含原短语“some words”的行 (例如,包含“some words of wisdom”的行,而非包含 “some noisewords”的行)。注意包围词组的‘"’符号是界定短语的操作符字符。它们不是包围搜索字符串本身的引号。
full text plugin的工作流程如下图所示:
下面,我们通过一个简单的例子来理解创建Full Text Plugin的过程
2)示例:对内建的布尔操作符进行改进,实现AND、OR和NOT操作(摘自)
实现思路:
基本思想是通过预读取的方法,在读单词时总是向后看有没有操作符,以决定当前单词的yesno,即是否是需要匹配的单词。
? 在AND前后的word yesno= 1
? 对于foo AND NOTbar 需要向前看两个单词
? wd1 OR wd2 ,前后的yesno = 0. 但当包含AND时,例如wd1 or wd2 and wd3,wd2的yesno = 1;
? 对于类似wd1 andwd2 or wd3 and wdb4,需要使用子表达式来分离AND和OR
? 如果没有使用操作符,例如wd1 wd2 转换为wd1 OR wd2
代码如下:
/*必要的头文件*/
#include
#include
#include
#include
/*用于辅助记录分词*/
typedefstruct{
char*start;//在字符串中的起始指针
intlen;//长度
intyesno;//是否被忽略
}WORD;
/*找到s和end间的第一个单词*/
staticchar*get_word(WORD*word,char*s,char*end)
{
word->yesno = 0;
while(s
s++;
word->start = s;
while(s
s++;
word->len = s - word->start;
returns;
}
staticintandor_parse(MYSQL_FTPARSER_PARAM*param)
{
/*需要解析的文档*/
char*end = param->doc + param->length;
char*s = param->doc;
WORDword, next;
MYSQL_FTPARSER_BOOLEAN_INFO bool_info =
{ FT_TOKEN_WORD, 0, 0, 0, 0, 0, 0 };
/*获取第一个单词*/
s = get_word(&next, s, end);
for(;;)
{
word = next;
/*向后看一个单词*/
s = get_word(&next, s, end);
/*已解析完文档,返回0*/
if(word.start >= end)
return0;
/*首先判断是否为boolean mode*/
if(param->mode == MYSQL_FTPARSER_FULL_BOOLEAN_INFO)
{
/*检查下一个单词是否为AND*/
if(next.start
if(word.yesno == 0){//当前单词之前没有AND
bool_info.yesno = 0;
bool_info.type = FT_TOKEN_LEFT_PAREN;
/*���加子表达式开始标记*/
param->mysql_add_word(param, 0, 0,&bool_info);
/*置当前单词yesno为1,表示不可忽略*/
word.yesno = 1;
}
/*读下一个单词*/
s =get_word(&next, s, end);
/*如果下一个单词为”not” 例如,word1 and notword2*/
if(next.start
/*继续读下一个单词*/
s = get_word(&next, s , end);
/*忽略该单词*/
next.yesno = -1;
}else
next.yesno= 1;//AND的下一个单词
}
else
if(next.start
/*获取下一个单词*/
s = get_word(&next, s, end);
bool_info.type = FT_TOKEN_WORD;
bool_info.yesno = word.yesno;
}
/*将当前单词加入到param中*/
param->mysql_add_word(param,word.start, word.len, &bool_info);
/*if there isAND before current word and no AND after it ,need to end subexpression*/
/*如果当前词之前有AND,并且当前词之后没有AND,则结束子表达式*/
if(word.yesno && !next.yesno){
bool_info.type = FT_TOKEN_RIGHT_PAREN;
param->mysql_add_word(param, 0, 0,&bool_info);
}
}
}
/*声明插件结构体*/
staticstructst_mysql_ftparser ft_andor =
{
MYSQL_FTPARSER_INTERFACE_VERSION,
audor_parse,
NULL,/*init,SET NULL */
NULL/*deinit,SET NULL*/
};
mysql_declare_plugin(andor)
{
MYSQL_FTPARSER_PLUGIN,
&ft_andor,
"andor",
"Sergei Golubchik",
"A Full-Text AND/OR boolean parser",
PLUGIN_LICENSE_GPL,
NULL,
NULL,
0x0100,
NULL,
NULL,
NULL
}
mysql_declare_plugin_end;