范德萨发而为
全部博文(392)
分类: C/C++
2013-06-17 22:48:30
* 数据库 – Database
什么是数据库?wiki上是这么说的,数据库是以一定组织方式储存在一起的,能为多个用户共享的,具有尽可能小的冗余度的、与应用彼此独立的相互关联的数据集合。在Xapian中也有这样一个概念,所有的Xapian操作都是围绕数据库来的,在索引建立的时候,所有文档(Document)都会被放入数据库中,索引建立,Xapian有多种数据库格式,下面会有介绍,而查询也是涉及到数据库的,它会返回与查询条件最匹配的结果。最常见的索引数据库就是倒排索引,也就是词到文档的一种映射关系,还有一些词的统计信息,如TF-IDF,%E2%80%93idf, 主要是用来计算文档的权重,还有查询条件与文档的相似度用的,据说Google有几百种因素来决定其查询结果的排序。当然,数据库还存储一些文本信息,如文档摘要,一些文件路径等信息,数据库还存储了一些词组的拼写与同义词的信息,以此来更好的优化查询条件,
Xapian有多种后台的数据库存储模型,默认的是为Chert,它使用了一种叫copy-on-write的B+树来做其数据结构,很多现有的Xapian数据库都支持事务,你可以把一批命令放在一个事务中运行,但是,当然的数据库只支持单个数据库写对象存在,也就是说在创建一个DataBaseWritable对象的时候,会对数据库进行加锁,如果另一个写数据库对象再去写这个数据库时,会出现DatabaseLockError错误,但是多个读对象是同时存在于同一个数据库。
当打开一个数据库准备进行读操作时,会创建一个找开数据库的镜像,这样有写操作时,读对象是不可见的,除非读对象运行reopen()操作。这样读/写操作就隔离了。现在的Xapian多版本同步还是有一些限制的,特别是当数据库有两个版本同时存在时,也就是说有多个读,一个写数据库操作时,当写数据库只修改了数据库,运行了一次commit时,是没问题的,但是当写数据库又运行了第二次commit时,读数据库操作会收到了一个Xapian::DatabaseModifiedError,在这种情况下,读数据库操作要更新其数据库的镜像版本,使用reopen()操作,这个要在编程上注意一下。
Xapian还有一个remote后端数据库,数据库服务端与客户端通过自定义的网络协议来通讯。Xapian还有一个特点是可以同时对多个数据库进行查询,并且对结果进行合并,这个特点可以结合remote DB来使用,这样可以横向扩展数据的容量,一个查询条件可以同时被多台后台查询服务运行,达到查询集群的目的。
Xapian同时支持数据库的复制,而且只复制那些变更过的索引数据,这样可以使用数据冗余,达到负载均衡的目的。
* 文档与文档数据
文档是数据库中一个索引对象与查询返回对象的表示,当建立一个搜索引擎的时候,首先要问自己的是系统中的文档是怎么表示的,如果你是对关系数据库进行索引,那一个文档可以是表中的一条记录,如果是对HTML进行索引,那一个文档就可以是一个HTML,或者HTML中的一个标签,每一个文档在一个数据库中都有一个唯一的ID号,叫做Document ID,其范围是32bit,一个文档(Document)有三部分组成,数据(data),词集(terms),值域集(values)
其中data代表一个文档的关系数据区,Xapian只负责对每个文档的data进行存储,不做分析处理,可能存储的时候会用zlib进行压缩,这个data可以是文档的部分或者全部数据。最常用的data区存储的数据是一些查询时要返回的数据,如文档的路径,日期等文档的元数据可以存储在这个地方,当然你可以使用一定的数据结构,如XML,JSON,protobuf等结果。
其中的terms就是文档分析出来的词的单元,它是最基本的查询单位,查询的过程简单来说就是把用户的查询进行分词,再把分词后的结果与索引的文档分词进行比较,返回包括这些词的文档。当然,Xapian对于分词的索引不仅仅是存储一个文档所对应的term,还有它的位置信息,词的文档频率,总的频率,这些信息被文档打分器提供文档分数的计算依据,
最后是values,首先values也是terms,只是它是一种更加灵活的terms,每一个被索引的文档都有一系列的values,每一个value的组成是一个二元组,其中K是value的solt,相当于一个id号,它的范围是unsigned int32,而Value是一个值,一般是一个String,也可以是Float,Double,但是都要通过其接口转换成String类型才能存储,这个方法是sortable_serialise,它可以对非String的value进行系列化,在查询的时候对其进行反序列化。这些values的作用是在查询的时候提供更加灵活的筛选条件,如我想把查询的结果文档按特定的字段排序,如价格,如果价格范围,这些值都会影响到文档的排序分数。values的另一个作用是可以对文档结果进行特定字段的聚类。
* 分词器
词器主要的功能是对于用户输入的文本进行分词,产生一系列的term,再把这些terms加入Document中去。
当然在分词的时候你可以加入一些词的过滤,词的特定域的处理,因为在Xapian中没有像Lucene一样有Field的概念,Xapian一般的解决方法是通过在每一个词前面加一个前缀来解决这个问题,不同的前缀表达这个词隶属于不同的Field. 需要注意的是,在Xapian中,如果你在索引的时候使用了TermGenerate来进行分词,那在查询的时候一定要使用QueryParser来对查询条件进行解析。
* 索引限制
一下是索引数据的一些限制:
Term Length:一个词限制在256个字节内,
Document Data:一个data区不能大于100MB,默认是8KB
Document value:和一个data区的限制是一样的,但一般建议value不要太大
Document ID: 当前范围是32bit,大概在43亿左右,文档删除的ID号不会被重新利用,除非你对数据库进行compact
B-tree block number: 目前支持最大为32bit个块
OS file size:所有操作系统对于单个文档的限制对于Xapian都适用,如ext4对于单个文件的大小为16TB,
Document length:文档长度的存储限制为unsigned 64bit
查询
查询Query提供了一种数据库文档查询的机制,最简单的一个查询条件就是提供一个term,找到包括这个term的所有文档,复制一点的查询有Boolean查询,组合查询,范围查询等查询。
查询解析
查询解析相当于一个解析器,其输入是用户输入的查询条件,输出是Xapian Query对象,如上面的简单查询,词组查询,Boolean查询等查询。
匹配器
当你把查询给Xapian运行后,会返回一个匹配器,你可以遍历这个匹配器,得到相应的命中文档信息,匹配器中的每个匹配项都是一个二元组,,每一个参数是文档分数,第二个是命中的文档对象,分数的诸一般是使用BM25算法来计算的,当然用户可以自定义分数算法;还有就是匹配文档的排序也可以定义,不一定按分数来,如可以按Document value的价格来排序。
转自:%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B02/