xapian搜索系统存储结构解读
- posting list table 保存了被每一个term索引的document,实际上保存的应该是document在database中的Id,此Id是唯一的。这个就是倒排表。
- record table 保存了每一个document所关联的data,data不能通过query检索,只能通过document来获取。这个相当于快照。
- term list table 保存了索引每个document的所有的term。这个相当于正排表。
-
position list table 保存了每一个Term出现在每一个document中的位置。就是term位置表。
其他可选的表还包括,value table 保存了每一个document的values,values是用作保存、排序或其它作用的。 + spelling table 保存了拼写纠正的数据。 + synonym table 保存术语的字典,例如NBA、C#或C++等。
目前最新版本的xapian,一个表一般会包含三个数据,如termlist表会被存储为以下三个文件“termlist.baseA”、“termlist.baseB”、“termlist.dB”。在这些文件中,其实只有”.db”文件存储了真实的数据,“.baseA”和“baseB”文件是用作跟踪如果于“.dB”文件中查找数据。
图 1 一个实际的xapian文件列表示意图
Xapian::Document doc; doc.add_term("K你好"); doc.add_term("K那里"); //posting是带position的term doc.add_posting("K吃饭", 14); doc.add_posting("K玩耍", 8); /* 这里最好先用一个map<string, int>放置value的名称和索引的配对 这里使用起来像Lucene的SortField一样了。 */ doc.add_value(1, "1"); doc.set_data("你好啊,在那里玩耍呢?还没吃饭吗?"); //创建一个可写的db Xapian::WritableDatabase db("c:\\db"); //将document加入到db中,返回document的id,此id在db中是唯一的 Xapian::docid id = db.add_document(doc); //刷新到硬盘中 db.flush();
获取document信息的例子:
//获取 Xapian::Document doc = db.get_document(id); string v = doc.get_value(1); printf(v);//输出 string data = doc.get_data(); printf(data);//输出"你好啊,在那里玩耍呢?还没吃饭吗?" for (Xapian::TermIterator iter = doc.termlist_begin(); iter != doc.termlist_end(); ++iter) { printf(*iter);//依次输出term和posting }
读取倒排列表(posting table的例子)
相关的类主要有两个,一个是PositionIterator,一个是PostingSource
其中
PositionIterator用来遍历一个term的所有docid列表
PostingSource则用来提供postings的扩展数据资源。
string t_name = "K你好";
cout<<"is exist "<<db.term_exists(t_name) <<endl;
PostingIterator term_begin = db.postlist_begin(t_name);
PostingIterator term_end = db.postlist_end(t_name);
for (PostingIterator iter=term_begin; iter != term_end ; iter++)
{
cout<<"doc id "<<*iter<<endl; //读取docid
cout<<"term freq "<<iter.get_wdf()<<endl; //读取文档内词频,tf
}