eaglet

本博专注于基于微软技术的搜索相关技术
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

HubbleDotNet 可以非常方便的对数据库现有表或视图创建全文索引,整个过程人工干预的时间不超过5分钟。我将用几个篇幅来阐述如何对现有数据表创建全文

索引。本篇将重点介绍如何创建 Updatable模式的全文索引。

Updatable 和 Append only 的共同点都是被动模式建索引,其区别在于采用 Updatable 模式为数据库现有表建立的全文索引可以添加,修改和删除,而

Append only 模式只能做添加和删除(Append only 模式删除不能自动,要通过程序来删除),不能修改。Updatable 模式索引同步要比 Append only 复杂很多,

详见自动和现有表同步,所以如果你的表只是进行添加和删除操作,没有修改操作,建议用 Append only 模式,否则用 Updatable 模式。

在对现有表创建全文索引前,我们还是需要先在 HubbleDotNet 中创建一个数据库,

如何创建数据库见:HubbleDotNet 开源全文搜索数据库项目--创建、删除数据库

创建好HubbleDotNet的数据库后就可以开始对关系数据库中现有表或视图建全文索引了。

下面我以Test库的EnglishNews 表为例,讲解如何针对现有表创建全文索引。

 

image

 

这是SQL SERVER的 Test库中 EnglishNews 表的结构

在HubbleDotNet 中建索引表

打开查询分析器,在News 库这个节点点右键选 Create Table,如下图所示

 

image

 

 

image

 

 

如上图所示点击Create table 后会出现这个界面,按照界面提示,输入HubbleDotNet 的表名,这里输入 EnglishNews,这个名字不一定要和数据库的名字相同。

再输入全文索引所在目录,选择数据库适配器,这里由于我对应的关系数据库是SQLSERVER 2005,所以选SQLSERVER 2005, 这个适配器适用于

SQL SERVER 2005 及以后的所有版本。然后再配置一下关系数据库的连接字符串,这个连接字符串用户和对应的关系数据库连接,如果需要连接远程数据库,

只需要在这里指定Data Source = 远程IP地址就可以了。点下面的Test DB Connection String 按钮测试连接字符串没有问题,点Next 进入下一步。

 

选择索引模式

 

image

 

 

如上图所示,由于是被动索引模式,我们选择 Build Index from exist table

Exist table Name or View Name 这里输入数据库中对应表的表名,这里输入 EnglishNews。 由于HubbleDotNet 不但可以对现有表做索引,

也可以对视图做索引,所以如果被索引的不是表而是视图,只要在这里填写数据库中对应的视图名就可以了。

由于这个表不但要添加删除,还要修改,这里我们选择增量模式为 Updatable 模式。

点Next 进入下一步

 

配置索引字段

 

image

 

 

如上图所示,HubbleDotNet 会自动从数据库中读取表结构,帮助用户生成索引表结构。

Updatable 类型索引,数据库的现有表必须有一个Int 或 Bigint 类型 Id 字段(ID Field) 这个字段的字段名可以为除DocId以外的任意名字。

这个字段必须设置为Untokenized 索引类型。这个字段必须是自增长的。

如果被索引的表的主键不是int或bigint 类型,比如vchar 类型字段做主键,那么我们必须在被索引表中插入一个 int 类型或bigint 类型的自增长字段,

并为这个字段建唯一性索引,然后将 ID Field 指向这个字段才行。

设置完所有字段后,点击下一步

 

完成索引

image

 

这一步列出创建语句,你可以做最后的检查,如果确认没有问题,点Finish。建表语句如下,你也可以不通过建表界面,直接写建表语句来建立索引表。

 

[IndexOnly]
[DocId('Id')]
[Directory ('d:\test11\EnglishNews\')]
[DBTableName ('EnglishNews')]
[DBAdapter ('SQLSERVER2005')]
[DBConnect ('Data Source=(local);Initial Catalog=Test;Integrated Security=True')]
Create table EnglishNews
(
Id BigInt Untokenized NULL default 0 ,
GroupId Int Untokenized NULL default 0 ,
SiteId Int Untokenized NULL default 0 ,
Title NVarchar(max) Tokenized Analyzer 'EnglishAnalyzer' NULL default '' ,
Content NVarchar(max) Tokenized Analyzer 'EnglishAnalyzer' NULL default '' ,
Time DateTime Untokenized NULL default '1900-1-1' ,
URL NVarchar(max) NULL ,
ImageUrl NVarchar(max) NULL 
);

 

这时将提示

 

如果你打算马上就开始索引,选 Yes

这时将进入 Rebuild Table 界面

image

点Rebuild 就可以开始为EnglishNews 这个现有表创建全文索引了。

这里需要注意的是:

Updatable 模式只能对空索引进行Rebuild,就是说如果HubbleDotNet 中已经有了这个表的索引记录,哪怕只有一条,就不能再继续 Rebuild 了,

这时只能点 RebuildWholeTable 对全表的索引清空后重新Rebuild。如果想在原来索引的基础上增量或修改,需要使用HubbleDotNet 提供的自动

同步功能来完成。 如何用自动同步功能,见:自动和现有表同步

 

image

 

全文索引建立完以后,我们可以优化一下,如下图所示

image

 

优化完以后,就可以搜索了。(不优化也可以搜索,性能会慢一些)

下面看看怎么搜索

搜索新闻

示例1

搜索标题包含 abc news to cut 这几个关键字中任意一个关键字的所有记录,并按匹配度排序

SQL 语句:
select top 10 Id, Title, Score from EnglishNews where title 
match 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' order by score desc
结果:

image

 

单词分量后面跟的参数含义如下

第一个参数表示这个单词分量的权值,这里为5000。

第二个参数表示这个单词分量在输入的被搜索的句子中的其实位置,如这里“abc”的位置为0,news的起始位置为 3.

top 10 表示输出前10条匹配的记录

这里可以看出,完全匹配的记录,得分最高。

 

示例2

搜索标题包含 abc news to cut 这几个关键字中所有关键字的记录,并按匹配度排序

SQL 语句:

select top 10 Id, Title, Score from EnglishNews where title contains 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' 
order by score desc

 

结果:

image

采用 Contains 搜索,可以进行精确匹配,这里我们发现采用 Contains 搜索出来的数据要比 Match 少很多。因为只有

同时包含abc news to cut 这四个单词的记录才会被输出出来。

 

再进一步,由于  to 这个词太常见,我们希望匹配同时包含 abc news cut 这三个单词的记录,并且记录中如果包含 to ,

则得分比不包含to 的得分高。这种搜索方法已经很解决 google 或 baidu 的搜索方法了,google 中如果输入关键字中包含停用词,

对非停用词采用与的方式匹配,对停用词采用或的方式匹配,但如果记录中包含要匹配的停用词,则得分比不包含的要高。

SQL 语句:

select top 10 Id, Title, Score from EnglishNews where title contains 'abc^5000^0 news^5000^3 to^5000^7^1 cut^5000^9' 
order by score desc
结果:

image

这里我们看出,多出了一条记录,这条记录排在第三位,和前两条记录比起来,这条记录没有 to 这个单词。

to 这个单词分量后面跟的参数说明:

to^5000^7^1

前两个参数和其他单词的意思一样,一个为权重,一个为位置。

第三个参数为标志字段,1 表示可以为或。

示例3

搜索标题包含 abc news to cut 这几个关键字中任意一个关键字的记录,并按匹配度排序,同时按 GroupId 字段做统计,

输出记录最多的10个groupid

SQL 语句:

 
[GroupBy('Count', '*', 'GroupId', 10)]
select top 10 Id, Title, Score from EnglishNews where title match 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' 
order by score desc
 

结果:

 

image

 

最后一个参数 10 是可选参数,表示返回前10个最多的分组统计结果,如果不填,返回所有分组统计结果。
Group By 字段必须为 untokenized 类型索引字段且不能是字符串类型。
这个语句执行后,会输出2个DataTable 第一个是 select 语句的结果集,第二个是group by 的结果集。也就是说在全文搜索时同时进行分组统计,

这样使用起来更方便,而且速度更快。

 

再进一步

[GroupBy('Count', '*', 'GroupId', 10)]
[GroupBy('Count', '*', 'SiteId', 10)]
select top 10 Id, GroupId, SiteId, Title, Score from EnglishNews where title match 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' 
order by score desc
 
image 
这个语句同时输出正对 GroupId 和SiteId 两个字段的统计结果。很多电子商务网站需要在搜索的同时显示多个分组的统计结果,HubbleDotNet 
可以通过上面语法一次输出
出来。而且HubbleDotNet 的 GroupBy 功能是在底层进行统计的,比Lucene 的统计需要在结果输出后再通过程序进行过滤统计要简单快速很多。
 

GroupBy 部分的伪SQL 语句是

select top 10 GroupId, count(*) as count from englishnews where title match 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' 
group by GroupId order by count desc
 

再进一步

[GroupBy('Count', '*', 'GroupId,SiteId', 10)]
select top 10 Id, GroupId, SiteId, Title, Score from EnglishNews where title match 'abc^5000^0 news^5000^3 to^5000^7 cut^5000^9' 
order by score desc

image

 

上述语句可以针对多个字段进行分组统计。要注意的是多字段 GroupBy 时,多个字段的占用字节数总和不可以超过8字节。及最多2个int类型,

或者8个tinyint类型。

 

更多例子见 HubbleDotNet 开源全文搜索数据库项目--为数据库现有表或视图建立全文索引(一) Append Only 模式

 

返回 Hubble.net 技术详解