该spellfix1虚拟表可用于搜索大词汇表以查找紧密匹配项。例如,spellfix1可用于建议对拼写错误的单词的更正。或者,它可以与FTS4一起使用,以使用可能拼写错误的单词进行全文搜索。
spellfix1虚拟表的实现保存在其他扩展文件夹的SQLite源树中,尤其是在文件 ext / misc / spellfix1.c中。spellfix1虚拟表未包含在SQLite合并中 ,也不是任何标准SQLite构建的一部分。这是一个可加载的扩展。
加载了spellfix1扩展名后,将按以下方式创建spellfix1虚拟表的实例:
使用spellfix1创建虚拟表演示;
“ spellfix1”术语是spellfix模块的名称,必须如图所示输入。“演示”一词是您将创建的虚拟表的名称,可以对其进行更改以适合您的应用程序的需求。虚拟表最初是空的。为了使虚拟表有用,您需要用词汇表填充它。假设您在名为“ big_vocabulary”的表中有一个单词列表。然后执行以下操作:
插入演示(单词)从big_vocabulary中选择单词;
如果打算将此虚拟表与FTS4 表配合使用(用于对搜索词进行拼写更正),则可以使用fts4aux表提取词汇表:
插入demo(word)SELECT术语FROM search_aux WHERE col ='*';
您还可以为虚拟表的每个单词提供一个“等级”。“等级”是对该词的普遍程度的估计。数字越大,表示该词越常见。如果在填充表格时忽略等级,则假设等级为1。但是,如果您具有排名信息,则可以提供它,并且虚拟表会稍微偏向于选择更常用的术语。要从fts4aux表“ search_aux”填充等级,请执行以下操作:
插入演示(word,rank) SELECT术语,文档来自search_aux WHERE col ='*';
若要查询虚拟表,请在WHERE子句中包含MATCH运算符。例如:
从演示中选择单词,在其中匹配单词“ kennasaw”;
使用美国地名的数据集(源自 http://geonames.usgs.gov/domestic/download_data.htm),上面的查询返回20个结果,开头为:
Kennesaw 基诺沙 Kenesaw 永永 基纳克
如果将字符“ *”附加到模式的末尾,则会执行前缀搜索。例如:
从演示中选择单词,其中单词MATCH'kennes *';
产生20个结果,开始于:
Kennesaw 肯尼斯顿 肯尼森 肯尼 基恩斯 基恩
默认情况下,spellfix1表返回的结果不超过20个。(如果匹配次数较少,则返回的值可能少于20。)您可以通过在查询的WHERE子句中添加“ top = N”项来更改返回行数的上限,其中N是新的最大值。例如,要查看5个最佳匹配:
从演示中选择单词,在其中匹配MATCH'kennes *'并且top = 5;
spellfix1虚拟表中的每个条目都与一种特定的语言相关联,该语言由整数“ langid”列标识。默认的langid为0,如果没有其他动作,则整个词汇表是0语言的一部分。但是,如果您的应用程序需要使用多种语言进行操作,则可以在填充表时通过指定langid字段为每种语言指定不同的词汇表项。例如:
INSERT INTO demo(word,langid)SELECT word,0 FROM en_vocabulary; INSERT INTO demo(word,langid)SELECT word,1 FROM de_vocabulary; INSERT INTO demo(word,langid)SELECT word,2 FROM fr_vocabulary; 插入演示(word,langid)SELECT单词,3 FROM ru_vocabulary; INSERT INTO demo(word,langid)SELECT word,4 FROM cn_vocabulary;
用多种语言的项目填充虚拟表后,在查询的WHERE子句中使用“ langid = N”术语指定感兴趣的语言:
从演示中选择单词,其中单词MATCH'hildes *'并且langid = 1;
请注意,如果未在WHERE子句中包含“ langid = N”,则搜索将针对语言0(在上例中为英语)。所有spellfix1搜索均针对单个语言ID。无法一次搜索所有语言。
spellfix1虚拟表中的每一行都有一个唯一的rowid,其中包含七个列以及五个额外的隐藏列。列如下:
行号
单词
秩
距离
乏味的
分数
Matchlen
电话哈希
最佳
范围
srchcnt
听起来好像
命令
spellfix1虚拟表将创建一个名为“%_vocab”的影子表(其中%被虚拟表的名称替换;例如:“ demo_vocab”代表“ demo”虚拟表)。影子表包含以下列:
ID
秩
乏味的
单词
11
22
还有一个用于计算图案和单词之间的Wagner编辑距离或Levenshtein距离的功能。此函数显示为spellfix1_editdist(X,Y)。编辑距离函数返回将X转换为Y的“成本”。某些转换的成本高于其他转换。例如,将一个元音更改为另一个元音是相对便宜的,因为将常数加倍,或者省略了双常数的第二个字符。其他改造或更昂贵。这个想法是,编辑距离函数对于相似的单词返回较低的成本,而对于相距较远的单词返回较高的成本。在此实现中,任何单字符编辑(删除,插入或替换)的最大成本为100,而某些编辑(例如转换元音)的成本较低。
比较的“分数”是图案和单词之间的编辑距离,可通过单词等级的以2为底的对数向下调整。例如,距离为100但排名为1000的比赛得分为122(= 100-log2(1000)+ 32),而距离为100且排名为1的比赛得分为131(100-log2( 1)+ 32)。(注意:常数32会添加到每个分数中,以防止在编辑距离为零的情况下变为负数。)通过这种方式,经常使用的单词会获得较低的费用,这往往会将其移到列表的顶部。替代拼写。
拼写校正器的直接实现是将搜索词与词汇表中的每个单词进行比较,然后选择得分最低的20个单词。但是,词汇表中通常会有成千上万个单词,因此这种方法不够快。
假设要进行拼写校正的术语为X。为了限制搜索空间,X的等效项转换为类似k2的键:
键= spellfix1_phonehash(下(spellfix1_translit(X)))
然后,此键仅限于“范围”字符。默认范围值是4,但是可以使用WHERE子句中的“ scope = N”术语指定替代范围。密钥被截断后,将对词汇表中具有以缩写密钥开头的k2值的每个术语进行编辑距离。
例如,假设输入单词是“ Paskagula”。语音键为“ BACACALA”,然后将其截断为4个字符“ BACA”。然后,在k2值以BACA开头的4980个词表(总共272,597个词表)中运行编辑距离,从而产生“ Pascagoula”作为最佳匹配。
仅搜索具有匹配语言限制的词汇表术语。因此,同一表可以包含来自多种语言的条目,并且仅使用所请求的语言。默认语言区域为0。
与固定权内置瓦格纳编辑距离函数可以通过更换editdist3()与应用程序定义的权重,并支持unicode的,通过指定“edit_cost_table =编辑距离函数TABLENAME ”参数到spellfix1模块当虚拟表已创建。例如:
使用spellfix1(edit_cost_table = APPCOST)创建虚拟表demo2
通过在虚拟表的“命令”列中插入适当的字符串,还可以在运行时选择或取消选择editdist3()编辑距离函数:
插入demo2(命令)VALUES('edit_cost_table = APPCOST');
在上面的示例中,将询问APPCOST表以找到编辑距离系数。spellfix1模块名称中存在“ edit_cost_table =“参数,这导致使用editdist3()代替内置的编辑距离功能。如果APPCOST为空字符串,则使用内置的Wagner编辑距离功能。
通常,将编辑距离系数从APPCOST表中读取一次,然后存储在内存中。因此,对APPCOST表的运行时更改通常不会影响编辑距离结果。但是,在虚拟表的“命令”列中插入特殊字符串“重置”会使编辑距离系数重新读取APPCOST表。因此,当对APPCOST表进行更改时,应用程序应运行类似于以下内容的SQL语句:
插入demo2(command)VALUES(“ reset”);
上面的算法在大多数情况下效果很好,但也有例外。这些异常可以通过使用“ soundslike”列在虚拟表中添加其他条目来处理。
例如,许多希腊起源的单词都以字母“ ps”开头,其中“ p”是无声的。例如:诗篇,化名,牛皮癣,精神病。在另一个示例中,许多苏格兰姓氏都可以用首字母“ Mac”或“ Mc”拼写。因此,“ MacKay”和“ McKay”的发音相同。
通过在虚拟表中为同一单词添加其他条目,然后在“类似声音”列中添加其他拼写,可以为未按发音拼写的单词提供调节。例如,“诗篇”的规范条目应为:
插入演示(word)VALUES('psalm');
为了增强将“ salm”的拼写更正为“ psalm”的能力,请添加以下内容:
插入演示(word,soundslike)VALUES('psalm','salm');
只要每个条目具有不同的听起来值,就可以为同一个单词创建多个条目。请注意,如果未指定类似声音的值,则类似声音默认为单词本身。
下面列出了在某些情况下可能需要添加其他类似声音的条目的情况。具体条目将取决于应用程序和目标语言。
实现spellfix1虚拟表的源代码模块还实现了一些SQL功能,这些功能可能对使用spellfix1的应用程序或在开发使用spellfix1的应用程序时进行测试或诊断工作很有用。以下辅助功能可用:
editdist3(P,W)
editdist3(P,W,L)
editdist3(T)
spellfix1_editdist(P,W)
spellfix1_phonehash(X)
spellfix1_scriptcode(X)
spellfix1_translit(X)
editdist3算法是一种计算两个输入字符串之间的最小编辑距离(即Levenshtein距离)的函数。editdist3算法是对spellfix1的默认编辑距离功能的可配置替代。editdist3的功能包括:
它适用于Unicode(UTF8)文本。
该应用程序可以提供插入,删除和替换成本的表格。
可以在成本表中枚举多字符的插入,删除和替换。
要编程editdist3的成本,请创建一个如下表:
创建表editcost( iLang INT-语言ID c从TEXT,-从此转换文本 cTo TEXT,-将文本转换为此 iCost INT-进行转换的成本 );
费用表可以命名为任意名称-不必称为“ editcost”。该表可以包含其他列。唯一的要求是该表必须包含上面显示的四列,并准确显示名称。
iLang列是一个非负整数,标识一组适合特定语言的成本。editdist3函数将仅使用单个iLang值进行任何给定的编辑距离计算。默认值为0。建议只需要使用一种语言的应用程序对所有条目始终使用iLang == 0。
iCost列是将cFrom转换为cTo的数字成本。此值应为非负整数,并且应小于100。默认的单字符插入和删除成本为100,默认的单字符到单字符替换成本为150。成本为10000或更高被认为是“无限的”,并导致该规则被忽略。
cFrom和cTo列显示编辑转换字符串。任一列或两列都可能包含多个字符。或任一列(但不能同时包含两列)可能包含一个空字符串。当cFrom为空时,这就是插入cTo的成本。当cTo为空时,这就是删除cFrom的代价。
在spellfix1算法中,cFrom是用户输入的文本,而cTo是数据库中存在的正确拼写的文本。editdist3算法的目标是确定用户输入的文本与字典文本的接近程度。
费用表中有三个特殊情况条目:
c发件人 | 到 | 意义 |
---|---|---|
'' | '?' | 默认插入费用 |
'?' | '' | 默认删除费用 |
'?' | '?' | 默认替代成本 |
如果省略了上面显示的任何特殊情况条目,则将值100用于插入和删除,将值150用于替换。要禁用默认的插入,删除和/或替换,请将它们各自的成本设置为10000或更高。
成本表中的其他条目将特定字符转换为特定字符。特定转换的成本应小于默认成本,否则默认成本将优先,并且永远不会使用特定转换。
例如,成本表条目:
插入到editcost(iLang,cFrom,cTo,iCost)中 VALUES(0,'a','ä',5);
上面的规则说,用户输入中的字母“ a”可以与字典中的字母“ä”匹配,罚则为5。
插入到editcost(iLang,cFrom,cTo,iCost)中 VALUES(0,'ss','ß',8);
cFrom和cTo中的字符数不必相同。上面的规则说,用户输入上的“ ss”将与“ß”匹配,罚则为8。
如果在创建spellfix1虚拟表时将“ edit_cost_table = TABLE”选项指定为自变量,则spellfix1虚拟表将使用editdist3。但是,也可以使用内置的“ editdist3()” SQL函数直接测试editdist3。editdist3()SQL函数具有3种形式:
第一种形式从称为“ TABLENAME”的表加载编辑距离系数。任何先验系数都将被丢弃。因此,当尝试权重和权重表发生变化时,只需重新运行editdist3()的单参数形式即可重新加载修改后的系数。请注意,editdist3()SQL函数使用的编辑距离权重独立于spellfix1虚拟表使用的权重。
第二和第三种形式返回计算的字符串“ string1”和“ string2”之间的编辑距离,在第二种形式中,使用的语言ID为0,在第三种形式中指定了语言ID。