`
kmoving
  • 浏览: 12130 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

python xapian存储结构

阅读更多
在项目中为了支持搜索服务,我们使用xapian作为后端的搜索引擎.其因性能良好以及易用受到大家欢迎.下面是基本代码:
import xapian
import posixpath

def get_db_path():
    XAPIAN_ROOT = '/tmp/'
    xapian_user_database_path = posixpath.join(XAPIAN_ROOT, u'user_index')
    return xapian_user_database_path

def add_document(database, words):
    doc = xapian.Document()
    for w in words:
        doc.add_term(w)
    database.add_document(doc)

def build_index():
    user_database = xapian.WritableDatabase(get_db_path(), xapian.DB_CREATE_OR_OPEN)
    words = ['a', 'b', 'c']
    add_document(user_database, words)

def search(words, offset=0, length=10):
    user_database = xapian.Database(get_db_path())
    enquire = xapian.Enquire(user_database)
    query = xapian.Query(xapian.Query.OP_AND, words)
    enquire.set_query(query)
    return enquire.get_mset(int(offset), int(length))

def _show_q_results(matches):
    print '%i results found.' % matches.get_matches_estimated()
    print 'Results 1 - %i:' % matches.size()
    for match in matches:
        print '%i: %i%% docid=%i [%s]' % (match.rank + 1,
                                          match.percent,
                                          match.docid,
                                          match.document.get_data()
                                          )
if __name__ == '__main__':
    #index 
    build_index()
    
    #search
    _show_q_results(search(['a','b']))


虽然使用起来很简单,但是我一直对于他的存储引擎有些好奇,所以看了一下最新的存储引擎brass的实现.下面是整个数据目录的层次结构:
/tmp/user_index
flintlock
iamchert
postlist.baseA
postlist.baseB
postlist.DB //存储所有term 到 docid的映射.
record.baseA
record.baseB
record.DB //存储所有docid 到 相应的数据的映射
termlist.baseA
termlist.baseB
termlist.DB //存储所有docid 到 相应的 term的映射.

brass存储引擎采用的数据结构是BTree.所以上面每个*.DB都是存储一个BTree的.*.baseA/B则是存储相应的.DB的meta信息.包括这个大的数据文件有哪些数据块已经被使用,哪些空闲的bitmap,以及版本号等等相关信息.
BTree在xapian中表示为N Level.每个level对应于BTree的一层.并且维护这一层的一个cursor.用于指向当前正在访问的某一个数据块,以及数据块中的某一个位置.其中每个数据块的数据结构如下:
from @brass_table.cc
/* A B-tree comprises (a) a base file, containing essential information (Block
   size, number of the B-tree root block etc), (b) a bitmap, the Nth bit of the
   bitmap being set if the Nth block of the B-tree file is in use, and (c) a
   file DB containing the B-tree proper. The DB file is divided into a sequence
   of equal sized blocks, numbered 0, 1, 2 ... some of which are free, some in
   use. Those in use are arranged in a tree.

   Each block, b, has a structure like this:

     R L M T D o1 o2 o3 ... oN <gap> [item] .. [item] .. [item] ...
     <---------- D ----------> <-M->

   And then,

   R = REVISION(b)  is the revision number the B-tree had when the block was
                    written into the DB file.
   L = GET_LEVEL(b) is the level of the block, which is the number of levels
                    towards the root of the B-tree structure. So leaf blocks
                    have level 0 and the one root block has the highest level
                    equal to the number of levels in the B-tree.
   M = MAX_FREE(b)  is the size of the gap between the end of the directory and
                    the first item of data. (It is not necessarily the maximum
                    size among the bits of space that are free, but I can't
                    think of a better name.)
   T = TOTAL_FREE(b)is the total amount of free space left in b.
   D = DIR_END(b)   gives the offset to the end of the directory.

   o1, o2 ... oN are a directory of offsets to the N items held in the block.
   The items are key-tag pairs, and as they occur in the directory are ordered
   by the keys.

   An item has this form:

           I K key x C tag
             <--K-->
           <------I------>

   A long tag presented through the API is split up into C tags small enough to
   be accommodated in the blocks of the B-tree. The key is extended to include
   a counter, x, which runs from 1 to C. The key is preceded by a length, K,
   and the whole item with a length, I, as depicted above.


上面来自于xapian的注释已经很清楚的说明了每个block的数据构成.除了数据元信息,就是由item组成的小的数据单元.其中每个小的item包括I(整个数据单元的长度),K(数据单元key的长度+x(key标示符)),C(表示对应的这个key有多少个item组成,因为某一个key对应的value太大的话,会进行value切分.所以C就表示总计有多少分.而之前的那个x则表示这个单元是第几份数据,这个如果需要读取这个key的整个大value就可以根据序号x进行合并.),tag就是我们刚才说的key对应的value,只不过xapian把它定义为tag.因为他是一个通用存储结构,所以这样定义也比较说的通.比如说在一颗BTree的非叶子节点tag存储的是下一层数据块的地址.对于叶子节点来说则存储相关的数据.现在整个树的存储结构已经清晰的展示出来了.

这里面有一个问题比较有意思的是postlist的存储,设想某一个热点词包含有很多很多的docid,比如说有100w个.那么当我们进行增量更新的时候,想要把某个docid从这个term删除掉,那么怎么才能尽快查找到这个docid在哪个数据块中呢?作者采用了term+docid作为BTree的key的方式来解决这个问题.value则是所有的大于这个docid的docid.并且每个块设定一个大小.这样就能让我们能尽快的定位一个docid在哪个block中,而不用读取所有的block然后再去查找了.

xapian还支持多个reader,单线程writer的方式进行增量更新.采用的类似数据库中的MVCC的方式,这样就不会因为更新把读操作阻塞住了.

目前作者正在开发replication方式,可以支持增量更新到其他机器.这样就能做到数据可靠(不会应为单机磁盘损坏导致数据丢失)以及高可用性(单机不可用,应用层可以切换到备用机器上)了.

BTW:我这两天看了xapian devel的邮件列表,虽然没有提交问题,但是看了作者(Olly Betts)对于每个问题都会给出耐心又详尽的答复,他人真的是很好.很是佩服.
分享到:
评论

相关推荐

    python xapian 简单应用

    在处理过程中,Xapian提供了一种高效的数据结构,如`Document`,用于存储这些信息。 在分词阶段,可能需要自定义分词规则,这可以通过实现`xapian.TermGenerator`接口来完成。默认的分词规则可能不适用于所有情况,...

    xapian-bindings:元软件包可简化针对Python的xapian-bindings扩展的安装。 尚未完全发挥作用

    xapian-bindings是一个元软件包,可简化针对Python的扩展的安装。 它根据安装的的版本确定要使用的xapian-bindings的版本。 下载并提取源代码; 然后运行./configure , make和make install 。 该项目与项目没有...

    xapian_doxygen_win

    【Xapian全文检索库】 Xapian是一个强大的开源全文搜索引擎库,专为高效的信息检索设计。它由C++编写,提供了丰富的API供开发者在各种应用程序中集成全文搜索功能。Xapian的核心特性包括高效的倒排索引、多字段搜索...

    xapian的使用

    首先,我们要了解Xapian的基本结构。Xapian的核心组件包括索引器(Indexer)和查询处理器(Query Processor)。索引器负责处理原始数据,创建索引,而查询处理器则解析用户输入的查询,然后在索引上执行搜索。 1. *...

    基于Xapian站内检索的设计与实现

    ### 基于Xapian站内检索的设计与实现 #### Xapian概述 Xapian是一个开源的搜索引擎库,采用通用公共许可证(GPL)发布。它最初是用C++编写的,通过绑定支持多种编程语言,如Perl、Python、PHP、Java、Tcl、C# 和...

    Xapian-1.2.22 windows下编译

    《Xapian-1.2.22在Windows环境下使用Visual Studio 2005进行编译的实战指南》 Xapian是一个强大的全文搜索引擎库,因其高效、可扩展和高度可定制的特性而在信息检索领域广泛应用。然而,对于Windows平台的开发者来...

    基于xapian搜索引擎的设计

    以Xapian 为核心开发一个搜索程序,以13 年第一季度的新浪新闻为检索目标,自行设计文档解析程序、调用xapian 建索引并实现一般检索、以及一个特殊的修饰符搜索功能(如url 搜索、标题搜索、时间搜索等),程序运行...

    C++开源搜索引擎xapian开发入门demo

    Xapian提供了C++、Python、Perl等多种语言的API,这里我们主要关注C++接口。首先,你需要创建一个`Database`对象,它代表了存储索引的物理位置。然后,使用`WritableDatabase`创建或者打开一个数据库,进行写入操作...

    xapian-core-1.4.9-vs2017-x64-release.zip

    Xapian是一个高性能、可扩展的开源搜索引擎库,支持多种编程语言,如C++、Python、Perl、Java等。它提供了一套完整的索引和搜索机制,包括倒排索引、模糊查询、布尔运算、相关性评分等功能,适用于文档管理、信息...

    基于Xapian和PHP的高性能站内搜索系统方案设计.pdf

    Xapian支持多种编程语言,包括PHP、Python、Java等。 四、基于Xapian和PHP的高性能站内搜索系统设计 本文提出了一种基于Xapian和PHP的高性能站内搜索系统设计方案。该系统使用Xapian作为搜索引擎库,使用PHP作为...

    python分布式爬虫打造搜索引擎

    同时,可以使用Whoosh、Xapian等本地搜索引擎库,如果数据量较小,也可以直接存储在SQLite或MySQL数据库中。 7. **前端展示**:最后,设计一个简单的前端界面,用户可以通过输入关键词,从搜索引擎中检索已爬取的...

    xapian_text_index

    索引是将非结构化的文本数据转化为可供快速搜索的数据结构的过程。Xapian提供了丰富的API,使得开发者可以方便地创建、更新和查询索引。在C++中,我们通常会创建一个Xapian::WritableDatabase对象来写入索引,以及一...

    搜索引擎技术教程 网络搜索引擎原理-第7章 Xapian简介 共39页.pptx

    #### 六、Xapian的内部结构 - **Documents**:每个文档由一个唯一的整数ID标识,没有字段的概念。 - **Terms**:带位置信息的词或短语,用于文本搜索。 - **Values**:短字符串,用于二进制范围搜索和排序。 - **...

    如何使用C#在Windows上编译和使用Xapian

    在Windows平台上使用C#编译和使用Xapian搜索引擎是一个技术性的任务,涉及到多个步骤和注意事项。Xapian是一款开源的信息检索库,它提供高效、灵活的全文搜索和相关性排名功能。以下是一些关键知识点: 1. **C#与...

    djapian:Django 的高级 Xapian 集成

    注意:在 mod_python 环境中 Xapian (&lt; 1.0.13) 存在。 所以要小心。 注意:在版本中引入了数据库架构向后不兼容的错误修复 - Change模型已将其object_id字段类型从整数切换为字符串。 ###特征 在这种情况...

    xapian-core-1.4.18-3.el8.x86_64.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

    细细品味架构·基于Xapian的垂直搜索引擎的构建分析(第2期)

    1.2.3 垂直搜索的引擎架构 1.2.4 垂直搜索技术和业务细节 1.2.5 现场答疑【Q&A】 2、知识扩展 2.1 淘宝类目及标题相关性分档计算方法 2.1.1 系统预测该关键词所对应的优先展示类目 2.1.2 已召回宝贝进行该关键词与...

    xapian-rack:轻松将 Xapian 与 Rack 集成

    安装将此行添加到应用程序的 Gemfile 中: gem 'xapian-rack'然后执行: $ bundle或者自己安装: $ gem install xapian-rack用法添加以下中间件: use Xapian::Rack::Search,:database =&gt; './xapian.db':roots =&gt; ['...

    Omseek (now Xapian)-开源

    Omseek已重命名为Xapian。 Xapian是一个用C ++编写的搜索引擎库,带有Perl,Python,PHP,Java,Tcl,C#和Ruby的绑定。 它使您可以轻松地向应用程序添加高级索引和搜索功能。

    xapian-core-libs-1.4.18-3.el8.i686.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

Global site tag (gtag.js) - Google Analytics