• Xapian使用入门


      关键字:搜索引擎、Xapian

      一篇拖了两三年的入门总结文章,今天发出来,一方面是自己的总结,另一方面是给自己和他人的备忘。读者需要对搜索引擎有初步了解,譬如了解倒排、term、doc、相似度打分等概念。

           Xapian是一个C++搜索引擎内核,提供了类似Lucene的功能,功能没有Lucene丰富,但可以满足常见的搜索需求:倒排检索、与或非查询、相关性打分排序等。

           下面对Xapian入门使用做介绍。

    1、Xapian安装-Linux

    下面介绍Linux下的编译安装。

    (1)下载源码

    https://oligarchy.co.uk/xapian(推荐)或者 https://github.com/xapian/xapian 下载xapian-core包。从github下载的包不包括./configure文件,需要自己使用autoconf生成。xapian-core不同版本对GCC有不同要求,可以看github下的INSTALL文件。

    (2)解压&安装

    解压:xz -d xx.tar.xz    tar xvf xx.tar                                                                                

    配置动态库:./configure --prefix=[your install path]                                                              

    配置静态库:./configure --prefix=[your install path]  --enable-static=yes --enable-shared=false 

    编译安装:make –j2 && make install

    注1:如果你编译出来的xapian lib静态库要作为你so库的一部分,那么在./configure 命令加上一句: CXXFLAGS=-fpic
    注2:valgrind 检查可能会执行很久,修改./configure 禁止掉它:在使用VALGRIND之前增加一行:VALGRIND=

    2、Xapian安装-windows

    这里采用MSVC做编译链接,方便后续对xapian源码做单步调试。因为对msys、vs命令行不熟悉,折腾了很久,特别感谢作者olly在xapian邮件组提供的帮助。

    环境:windows 7 &  Visual Studio 2017

    源码包:xapian-core-1.4.10 (注意:xapian1.2到1.4之间的一部分版本不支持windows编译安装)

    步骤如下:

    1. 安装Visual Studio 2017

    2. 安装msys2。下载地址:http://repo.msys2.org/distrib/x86_64/msys2-x86_64-20180531.exe;

    2.1 在msys2下安装make,

    pacman -S make

    可能需要设置镜像地址,参考:https://blog.csdn.net/callinglove/article/details/48601775

    3. 安装zlib。可以直接使用编译好的32位版本,下载地址: http://gnuwin32.sourceforge.net/downlinks/zlib-lib-zip.php  。有时候线上的版本可能缺少某些库函数,可以使用附件中的zlib。

    4. 启动msys2。首先,启动cmd;然后,在cmd下执行VS2017的环境变量批处理——vcvars32.bat(因为zlib是32位的,所以这里也选择32位),譬如:C:Program Files (x86)Microsoft Visual Studio2017ProfessionalVCAuxiliaryBuildvcvars32.bat;接着,继续在cmd下启动msys2, 命令:msys2_shell.cmd -use-full-path;然后,在msys2 shell下面执行 which cl,确认能找到cl;

    5、在msys2下,进入到代码目录,执行configure:

    ./configure LD=link CC="cl -nologo" CXX="$PWD/compile cl -nologo" CXXFLAGS="-EHsc -Z7" AR=lib CPPFLAGS=-IC:/zlib-1.2.3-lib/include LDFLAGS="-LC:/zlib-1.2.3-lib/lib" --prefix="C:/xapian-install"

    如果出现找不到zlib.h的错误,需要检查一下xapian目录下的config.log文件,可能是因为找不到unistd.h头文件导致的。解决办法:修改zconf.h的 #if 1,修改为 #if HAVE_UNISTD_H

    参考:https://stackoverflow.com/questions/22705751/cannot-open-include-file-unistd-h-no-such-file-or-directory

    6、./configure跑完之后,执行make

    7、执行make install

    8、创建VS2017 工程

    8.1 把项目设置为Release x86;
    8.2 在项目属性的 C/C++-->General 修改Addtional Include Directories,加上xapian的include路径;
    8.3 在项目属性的 C/C++-->Code Generation修改Release下的Runtime Library为 /MT (我们编译的xapian运行时库用的MT,需要确保一致)
    8.4 在项目属性中 Linker-->General修改Additional Library Directories,加上xapian的lib目录和zlib的lib目录;
    8.5 在项目属性的 Linker-->input中加上Rpcrt4.lib 和 Ws2_32.lib
    8.6 将zlib1.dll拷贝到跟编译生成的exe文件同目录下,否则exe启动会有错误提示:应用程序无法正常启动(0xc000007b)

    至此,就可以在VS2017下跑起xapian的demo程序,并对xapian的源码进行单步调试。

    demo github:https://github.com/cswuyg/xapian_exercise/tree/master/ram_xapian

    3、Hello World

      demo例子:对“中国篮球比赛”建索引,然后使用OR语法做检索,输出检索结果信息。

    代码:

    /***************************************************************************
     *
     * @file hello_world.cpp
     * @author cswuyg
     * @date 2019/01
     * @brief  xapian first demo
     *
     **************************************************************************/
    #include <iostream>
    #include "xapian.h"
    
    const char* const K_DB_PATH = "index_data";
    const char* const K_DOC_UNIQUE_ID = "007";
    
    /// 创建索引
    void createIndex() {
        std::cout << "--index start--" << std::endl;
        Xapian::WritableDatabase db(K_DB_PATH, Xapian::DB_CREATE_OR_OPEN);
    
        Xapian::Document doc;
        doc.add_posting("T中国", 1);
        doc.add_posting("T篮球", 1);
        doc.add_posting("T比赛", 1);
        doc.set_data("中国篮球比赛");
        doc.add_boolean_term(K_DOC_UNIQUE_ID);
    
        Xapian::docid innerId = db.replace_document(K_DOC_UNIQUE_ID, doc);
    
        std::cout << "add doc innerId=" << innerId << std::endl;
    
        db.commit();
    
        std::cout << "--index finish--" << std::endl;
    }
    
    /// 检索索引
    void queryIndex() {
        std::cout << "--search start--" << std::endl;
        Xapian::Query termOne = Xapian::Query("T中国");
        Xapian::Query termTwo = Xapian::Query("T比赛");
        Xapian::Query termThree = Xapian::Query("T足球");
        auto query = Xapian::Query(Xapian::Query::OP_OR, Xapian::Query(Xapian::Query::OP_OR, termOne, termTwo), termThree);
        std::cout << "query=" << query.get_description() << std::endl;
    
        Xapian::Database db(K_DB_PATH);
        Xapian::Enquire enquire(db);
        enquire.set_query(query);
        Xapian::MSet result = enquire.get_mset(0, 10);
        std::cout << "find results count=" << result.get_matches_estimated() << std::endl;
    
        for (auto it = result.begin(); it != result.end(); ++it) {
            Xapian::Document doc = it.get_document();
            std::string data = doc.get_data();
            Xapian::weight docScoreWeight = it.get_weight();
            Xapian::percent docScorePercent = it.get_percent();
    
            std::cout << "doc=" << data << ",weight=" << docScoreWeight << ",percent=" << docScorePercent << std::endl;
        }
    
        std::cout << "--search finish--" << std::endl;
    }
    
    int main() {
        createIndex();
        queryIndex();
        return 0;
    }

    makefile:

    OBJ=hello_world.o
    CC=g++ -std=c++11
    CFLAGS=
    XAPIANROOTDIR=/usr/local/app/cswuyg/xapian_proj/install/
    INCLUDE=-I$(XAPIANROOTDIR)include/
    LIBS=-lxapian
    hello_world: $(OBJ)
            $(CC) $(CFLAGS) -o hello_world $(OBJ)  -L$(XAPIANROOTDIR)lib $(LIBS)
    hello_world.o: hello_world.cpp
            $(CC) $(CFLAGS) -c hello_world.cpp $(INCLUDE)
    clean:
            rm *.o

    运行结果:

    --index start--
    add doc innerId=1
    --index finish--
    --search start--
    query=Xapian::Query((T中国 OR T比赛 OR T足球))
    find results count=1
    doc=中国篮球比赛,weight=0.308301,percent=66
    --search finish--

    demo github:https://github.com/cswuyg/xapian_exercise/tree/master/hello_world 

    本文所在:https://www.cnblogs.com/cswuyg/p/10402218.html

    附件:

    https://files.cnblogs.com/files/cswuyg/zlib-1.2.3-lib.7z

  • 相关阅读:
    ES6 promise 常用方法介绍
    js判断元素是否在可视区域里
    alert之后才执行
    jquery总结和注意事项
    java中unicode和中文相互转换
    html href页面跳转获取参数
    myBatis批量添加实例
    mybatis中返回自动生成的id
    遍历map的四种方法
    MyBatis魔法堂:Insert操作详解(返回主键、批量插入)
  • 原文地址:https://www.cnblogs.com/cswuyg/p/10402218.html
Copyright © 2020-2023  润新知