头部背景图片
zhaoyangkanshijie |
zhaoyangkanshijie |

全文搜索lucene5.3.1说明文档

1. 工作原理

2. 项目结构

3. 数据结构

4. 业务逻辑

工作原理

全文检索(Full-Text Retrieval)是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程。关于全文检索的特性,我们要知道:1,只处理文本。2,不处理语义。3,搜索时英文不区分大小写。4,结果列表有相关度排序。

参考:

  1. lucene全文检索精华
  2. 全文检索的基本原理
  3. Lucene5.3.1 API

(1) 分词器

lucene需要通过分词器(analyzer)拆分句子、词组,以便存储和搜索,本项目用的是IK分词器2012V5版本。

友情提示:创建索引的分词方法须与搜索时的分词方法一致。

(2) 创建索引

我们会从数据库拿到一些数据,每个字段对应lucene的每个域(field),经过分词处理的域的组合形成一个文档(document)。如下图:

  • 数据表

    | | 字段1 | 字段2 |
    | ——–| —— | —— |
    | id=1 | abc | abc |
    | id=2 | abc | abc |
    | id=3 | abc | abc |

  • lucene文档

    | | 域1 | 域2 |
    | ——–| —— | —— |
    | 索引1 | a,b,c | a,b,c |
    | 索引2 | a,b,c | a,b,c |
    | 索引3 | a,b,c | a,b,c |

当然,需要事先设置文档的保存路径(directory),设置文档的名字(type),创建写入器(IndexWriter),写入器导致数据每次的改动都要保存(commit)和关闭(close)。

(3) 搜索

(4) 索引表的增删改

  • 增(add):同创建索引
  • 删(delete):删除指定索引(deleteDocuments),删除全部索引(deleteAll)
  • 改(update):更新索引,机制为先删除再创建(updateDocument)

参考样例1

参考样例2

项目结构

  • Lucene531
    • src
      • com.search
        • SearchHelper.java –索引表的增删改查
      • com.model
        • SearchModel.java –数据结构模型类
      • com.servlet
        • InitialServlet.java –初始化索引表入口
        • ManagerServlet.java –索引表增删改入口
        • SearchServlet.java –搜索入口
      • com.util
        • EntryUtil.java –初始化索引表、定时任务、搜索组装
        • HelpUtil.java –工具函数
        • Output.java –异常信息打印
        • SQLUtil.java –获取数据库数据
    • config.properties
    • WebRoot
      • index.html –搜索页面
      • initial.html –初始化索引表页面
      • manager.html –索引表增删改页面

数据结构

  1. 数据模型 SearchModel.java

    与数据库表对应如下:

id(int) name(String) model(String) detail(String) classid(int)
Test id(int) name(varchar) model(varchar) detail(text/varchar) classid(int)
hits(int) updatetime(Date) other(String) visible(Boolean)
Test hits(bigint) updatetime(datetime) other(varchar) visible(bit/smallint)
classname(String)
TestClass classname(varchar)
  1. 搜索数据组装 EntryUtil.java

    2.1 json:空集合和搜索结果数量。(原因:搜索不到结果,或关键词长度小于2)

    数据样例:

    1
    2
    3
    4
    {
    “result” :[],
    “testCount”:”0”
    }

    2.2 test的json数据和test的搜索结果数量。(最多不超过500条)

    数据样例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    {
    “result” :
    [
    {
    “classid”:”1”,
    ”detail”:”aaa”,
    ”displayorder”:”1”,
    ”hits”:”999”,
    ”id”:”1”,
    ”model”:”sadsad”,
    ”name”:”sad”,
    ”other”:”asd”,
    ”updatetime”:”2012-08-17 16:22:00”,
    ”visible”:”true”,
    ”classname”:”asddd”
    },
    {...},
    ...,
    {...}
    ],
    “testCount”:”500”
    }

    2.3 增删改和初始化索引表

    成功:

    1
    [{“errCode”:0}]

    失败:

    1
    [{“errCode”:-1}]

业务逻辑

函数实现

  1. EntryUtil.java –初始化索引表、定时任务、搜索组装

    1.1 static 静态构造函数

    • 第一次访问会初始化索引表和设置定时初始化索引表任务。

      1.2 Boolean initializeIndex() 初始化索引表

    • 创建索引表

    • 返回标志符

      1.3 void setTime() 定时初始化索引表任务

    • 设置每天24:00调用初始化索引表函数

      1.4 String searchServer(String keywords,String type) 返回搜索数据

    • 过滤关键词长度小于2

    • 搜索关键词,并获得搜索结果数量
    • 数据组装(详见数据结构第2点)
  1. SQLUtil.java –获取数据库数据

    2.1 static SQLUtil getInstance() 获取数据库实例

    2.2 Connection getConnection() 数据库连接

    • 获取配置文件中的链接字符串
    • 设置数据库驱动
    • 获取连接并返回

      2.3 ArrayList getProductList() 获取test列表

    • 执行SQL语句

    • 填充数据模型(详见数据结构第1点)
    • 关闭连接

      2.4 SearchModel getProductChangedData(String id) 获取test改动数据

    • 执行SQL语句

    • 填充数据模型(详见数据结构第1点)
    • 关闭连接
  2. HelpUtil.java –工具函数

    3.1 String filterHtml(String html) 过滤危险字符

    • 去除js的&nbsp
    • 去除html及其属性
    • 将标点符号 Unicode空白符替换为“|”

      3.2 Boolean filterString_setBootst(String s) 判断是否常用词

    • 常用词包括aa,bb,cc,dd

      3.3 String[] mergeIdentical(String[] str) 合并字符串数组中相同的字符串

      3.4 String convertToJson(ArrayList datalist) 列表转json

      3.5 ArrayList fillDisplayorder(ArrayList datalist) 填充列表的displayorder项,按升序排列

      3.6 String responseFormat(String maindata,String dataCount) 数据组装函数

      3.7 日期和字符串相互转换函数

    • String dateToString(Date date)

    • Date stringToDate(String dateString)
  3. SearchHelper.java –索引表的增删改查

    4.1 FSDirectory getDirectory(String type) 创建文档

    • 获取配置文件的文档文件夹路径
    • 创建文件并返回

      4.2 String Token(String str) 分词

    • 使用IK分词,词组以“|”隔开

      4.3 boolean createIndex(ArrayList datalist, String type) 创建索引

    • 创建IK分析器 Analyzer

    • 创建文档 getDirectory
    • 配置分析器 IndexWriterConfig
    • 创建写入器 IndexWriter
    • 清空文档索引内容 deleteAll
    • 创建每一条索引 createSingleIndex
    • 保存和关闭

      4.4 boolean createSingleIndex(IndexWriter iwriter, SearchModel data) 创建一条索引

    • 新建文档 Document

    • 设置文档属性 FieldType

      • setStoreTermVectorOffsets 记录相对增量
      • setStoreTermVectorPositions 记录位置信息
      • setStoreTermVectors 存储向量信息
      • freeze 阻止改动信息
    • 创建域 Field

    • 设置域权重 setBoost
    • 向文档加入域 add
    • 写入文档 addDocument

      4.5 ArrayList search(String keywords, String type) 查询关键词

    • 过滤危险字符

    • 打开文档,创建分析器
    • 关键词分词
      • IK分词数组,权重最小
      • 纯数字和字母数组(字母和数字分开)
      • 纯数字和字母数组(字母和数字可以连在一起),权重最大
    • 使用多种搜索方式组合搜索(详见工作原理第(3)点)
    • 查询结果高亮

      • FragListBuilder使用SimpleFragListBuilder
      • FragmentsBuilder使用ScoreOrderFragmentsBuilder
      • FastVectorHighlighter
      • getFieldQuery
      • getBestFragment
    • 数据按需填充,如限制得分或条数

    • 关闭写入器和文档

      4.6 int searchByTerm(String field,String name,String type) 查找域目标数量

    • 通过精确查询,计算目标数量

      4.7 int getSearchCount(String keywords, String type) 获取搜索结果条数

    • 与搜索关键词的搜索逻辑相同,搜索完后计数

      4.8 索引增删改

    • boolean addIndex(SearchModel data, String type)

    • boolean updateIndex(String id, SearchModel data, String type)
    • boolean deleteAllIndex(String type)
    • boolean deleteIndex(String id, String type)
  4. Output.java –异常信息打印

    5.1 boolean createFile(String fileName,String filecontent) 创建文件

    5.2 boolean writeFileContent(String filepath,String newstr) 向文件中写入内容

函数关系

InitialServlet 初始化索引表流程

直接初始化索引,详见1.2

ManagerServlet 索引表增删改流程

  1. java获取post参数
  2. 判断type
  3. 判断id是否存在
    • 若存在:判断visible:1为更新索引操作;0为删除索引操作
    • 若不存在:判断visible:1为插入索引;0不做任何操作
  • visible:2.4
  • 更新索引操作:4.8
  • 删除索引操作:4.8
  • 插入索引:4.8
  • 异常:获取数据库数据为空

SearchServlet 搜索流程

大致流程:

0 1 2 3 4 5 6 7 8
1 1.1 1.2 1.3 return
4.3 4.8 4.4 return
2 1.4 3.1 4.5 4.7 3.5 3.4 3.6 return
avatar zhaoyangkanshijie blog