[置顶]Hubble.net 搜索引擎分析三
[置顶]Hubble.net 搜索引擎分析二
[置顶]Hubble.Net 搜索引擎分析一
Hubble.net 搜索引擎分析四
4.Hubble.Net查询过程
Hubble.net的查询过程为:首先在数据库中,通过列的match查询得到所需的原始数据。在通过倒排索引对象获取索引词的位置信息。最后组合(加亮)返回。
现已Hubble.net中的Dome项目为例子来说明Hubble.net的查询过程。如下模型图:
1.用户通过WebDome.Index.Search()方法查询数据。传递需要的参数:查询条件、索引目录、每页记录数、当前页数。返回查询时间、内部解析后的条件。
2.Search()方法内部,
1.>首先调用SqlCommand.GetKeywordAnalyzerStringFromServer()进行分词,GetKeywordAnalyzerStringFromServer()内部调用SP_FieldAnalyze存储过程,通过TCP达到服务器,最终调用SP_FieldAnalyze内的Run方法,最后调用IAnalyzer.Tokenize()分词。并返回结果。
2.>根据返回的分词构造SQL查询语句并调用SqlCommand.Query()查询数据。
A.Query()方法内部调用_SqlConnection. QuerySql()方法把SQL语句发送到服务器。并把返回的结果缓存起来。
B.服务器接受到SQL语句后,首先解析SQL语句生成List<TSFQLSentence>列表,并判断TSFQLSentence类型,根据不同的类型执行不同的方法,这儿调用ExcuteSelect()方法。
C. ExcuteSelect方法内部,首先判断Process data cache 获取程序集缓存。如果没有,在判断dbProvider.QueryCache 是否超时。如果超时,就查询数据库,根据SQL where条件查询DocId。
D.根据查询列和记录ID列表,调用dbProvider.Query()方法查询列值。而Query方法内部在调用IDBAdapter.Query()查询数据库值,并初始化文档列值,且返回。
3.> 根据文档ID列表和分词,调用SqlCommand.GetWordsPositions()方法获取词语在文档中的位置信息。GetWordsPositions方法调用SP_GetWordsPositions存储过程,并发送到服务器,服务器解析后调用SP_GetWordsPositions.Run方法。Run方法内部调用dbProvider.GetInvertedIndex()获取倒排索引对象,在通过invertedIndex.GetWordIndex()获取词语的阅读器,读取本词语关联的文档索引位置信息。
4.>根据以上返回的结果构造最后的结果,返回给用户。
注:Search()方法中构造的SQLselect between {0} to {1} * from News where content match {2} or title^2 match {2} order by。Where部分采用的是数据库全文搜素。然后在根据查询得到的文档ID和分词结果,查询分词对应文档中的位置信息。不知道这样是否好。我想应该是根据分词查询文档ID,然后在求各词语的并集,最后在根据文档ID获取原始信息。因为内存中已经有了词语的索引信息(文档ID,文档中的位置等)。
Hubble.net 搜索引擎分析三
3. Hubble.Net建立索引
通过前面的分析,我们知道一条记录(datarow)就是一个文档。所以实质是对datarow进行索引。我们根据Table类知道一条datarow有几个索引列,并通过其列名就可以后去对应的倒排索引对象,再使用倒排索引对象索引其对应值。对应的模型图如下:

1.一个数据表对应一个DBProvider对象,需要对某个表建立索引时,只需要通过其表名称获取对应的DBProvider对象就可.调用DBProvider. GetDBProvider(tablename) 静态方法。
2.把DataRows转换成List<Document>,在调用DBProvider对象的Insert方法。
3. Insert方法内,首先调用IDBAdapter.Insert(docs); 插入文档到数据库中。其次创建索引信息,根据文档的数据列类型,获取对应的倒排索引(InvertedIndex)对象。调用倒排索引对象的Index方法,并传入对应列值,文档ID,IAnalyzer对象。根据各列索引返回值(fieldvalue分词个数),组成Payload对象,以便调用PayloadFile.Save()方法存储。注数据列类型为Untokenized,直接把其值转换为int[] 数组。
4. 倒排索引(InvertedIndex)对象Index方法内部:首先调用IAnalyzer.Tokenize(text)分词,其次根据词语获取对应的WordIndexWriter对象,如果不存在就新建一个并记录到索引词列表,初始化WordIndexWriter对象的临时文档ID,TempRank值,本词语在文档中的位置(wordIndex.AddToTempPositionList(wordInfo.Position))。最后根据缓存文档个数,判断是否调用存储索引文件方法(StoreIndexToFile())。
5. StoreIndexToFile方法内部,循环获取需要保存的索引信息,并调用索引文件代理类IndexFileProxy的AddWordPositionAndDocumentPositionList(wordIndex.Word, docList)方法保存索引信息。最后调用IndexFileProxy对象的Collect()方法重新初始化一对新的索引文件(.hdx和.idx)以便下次索引信息存放。
6. IndexFileProxy对戏的AddWordPositionAndDocumentPositionList()内部,首先调用索引类IndexFile.AddWordAndDocList(wl.Word, wl.DocList);记录索引词对应的索引信息。最后把刚存储的索引文件信息记录到内存,以便查询使用。
注:IndexFileProxy类是IndexFile类的代理类,这儿使用了代理(Proxy)设计模式,简单的说就是调用IndexFileProxy对象的方法,间接的是调用IndexFile对象的对应方法。我想最终分布式索引也依赖于此吧。
7. IndexFile.AddWordAndDocList方法内,首先调用_IndexWriter.AddWordAndDocList(word, docList, out length);把索引词在文档中的索引信息写入到.idx和.hdx文件中,并返回在.idx文件中的位置和长度,以便记录在内存中。
8. IndexWriter.AddWordAndDocList方法内,首先循环DocumentPositionList in docList写入.idx中,每项之间用0隔开,最后在把其开始位置和长度写入到.hdx中。
至此创建索引完成。注:对象模型图,中的对象方法等,不是全部。因为本章写的是创建索引,所以只画出了与创建有关的
Hubble.net 搜索引擎分析二
1. Hubble.Net运行机制
根据第一章知识,我们知道Hubble.Net系统只存储索引信息,而索引文档另存储于数据库中。.我们知道Hubble.Net采用的是倒排索引技术,索引词关联文档信息。所以索引词成为系统的关键点。根据索引词建立对应的索引信息和查询索引信息。现在我们来重点分析.hdx和.idx类型文件,以及其在系统中的表现形式和整个系统的运行机制。
1.索引的建立是根据数据索引列。系统在创建Table时,会根据用户指定的数据索引列创建对应的索引文件。假如一个Table中有三列{title(索引类型Tokenized),url,content(索引类型Tokenized)}。系统会为此表自动添加两列,最终为{id(文档ID,记录插入数据库时,自动生成。系统中所有关于文档ID 的值都来与此),title,url,content, Score(文档的分数) }。此表最终{ title , content }两数据列需要建立其各自的倒班索引对象,用列名来区分。而且倒排索引对象建立各自的索引文件,文件名由7个数字加列名组成({d:7}+fieldname)。
2.倒排索引文件包含自己独立的索引词列表。当新建一个文档(记录)索引时,首先对其值进行分词,分别判断结果词是否已在索引词列表中,如果在就更新其对应的索引信息,如果不在就添加其到索引词列表。以此维护其自身的索引词列表,以便查询是使用。
3.系统搜素时,查询命令格式:fieldname command 词语 词语 词语 。查询命令以空格隔开。fieldname为列名,表示需要查询那一列索引。Command为查询方式。现在系统中已有三种查询方式:FullTextQuery、MatchQuery、MutiStringQuery。词语为用户指定的查询词,可以多词语查询。系统根据fieldname,获取对应的倒排索引对象,在根据倒排索引对象内部的索引词列表,查询“词语”,其结果根据command类型,组合结果,并最终返回给用户。
4.系统运行时,首先根据配置文件初始化:索引目录、IQuerys、IAnalyzers、IDBAdapters、数据表(Tables,一个表对应一个DBProvider对象。)、然后在根据表配置信息初始化倒排索引对象列表。倒排索引文件内部(IndexFile)在加载.hdx类型文件。在根据.hdx文件,加载索引词对应的索引文件名、位置、长度等信息到内存,至此初始化完成。当需要创建索引文档时,更新.hdx和.idx文件。需要查询时,配置索引词列表,获取索引文件信息,然后在根据位置、长度读取对应的文档ID、Count(词语在文档中出现的次数)、DATA(词语出现在文档中的位置列表)、Rank(权证值),根据Command组合查询结果并返回给用户。
5.合并(优化)索引。合并索引有四种类(OptimizationOption): Idle、Minimum、Middle、Speedy。合并索引文件只是在本列索引文件内合并索引文件。首先在当前索引目录下新建一个Optimize目录,合并就在词目录内完成。其次根据类型获取需要合并的索引文件列表。然后读取每个词在合并索引列表中的索引信息,统一写入到新的索引文件信息中(.idx),并记录新的索引位置信息(.hdx)。最后在内存中更新合并后的索引位置信息,删除合并前的索引文件。拷贝合并后的索引文件到当前索引目录内。
Hubble.Net 搜索引擎分析一
由于本人只关系搜索这方面的知识,所以只分析Hubble.Net内部关于搜索方面的知识。本人是一个业余爱好者,所以水平有限,望大家多多指点。
注:本人分析的是0[1].7.2.0-Src版本的代码。
1. Hubble.Net 文件信息
由于Hubble.Net是和数据库结合构建搜索系统的。所以Hubble.Net只记录文档的索引信息,而文档本身内容记录与数据库中。Hubble.Net文档信息如下:
1. *.hdx类型文件:记录索引词对应的索引信息。如索引词、在对应.idx文件中的位置和长度。
数据格式:size|postion|length|word size包含了postion、length、word的大小
2. *.idx类型文件:记录索引词在文档中的信息。如文档ID、当前索引词在文档中出现的次数(count),其值和Data.length相等、记录当前索引词在文档中出现的位置列表(Data)、记录文档的Rank值。
数据格式:Data.Length|DocId|Count|Rank|Data
注:.hdx和.idx是成对出现的。.idx记录索引词在文档中的信息,如个数,位置,Rank。.hdx记录索引词、索引信息在idx文件中的位置和长度。文件名构成:{d:7}+ Serial。
3. Payload.db类型文件:记录Table数据列信息、文档ID、数据记录每列的索引词个数。数据列信息包含每列的field.Name 、field.TabIndex、field.DataType、field.DataLength、field.IndexType。数据记录每列的索引词个数。
数据格式:field.Name +field.TabIndex+field.DataType+field.DataLength+field.IndexType(unicode MD5加密)|文档ID|Data(记录索引词个数)| 文档ID|Data(记录索引词个数)|…..
注:记录索引词个数等于每字段所以词个数列表。根据字段索引类型不同取值方法不同。Untokenized类型存储数据值本身,Tokenized类型存储数据值分词后的索引词个数。
4. tableinfo.xml类型文件:存储Table配置信息。如表名称、ConnectionString、数据库中表名称(DBTableName)、数据列信息(Fields)、_DBAdapterTypeName、_ForceCollectCount(创建索引缓存文档个数)、_IndexOnly(索引是否只读)、_QueryCacheEnabled(是否支持查询缓存)、_QueryCacheTimeout(超时时间)、_SQLForCreate(创建SQL语句)。采用XML序列化存储Table配置信息。
5. Delete.db类型文件:存储删除文档列表。
数据格式:DocID| DocID| DocID| DocID….