搜索引擎lucene点滴

在项目中有用到搜索引擎lucene。现将学到的lucene中的一些知识点和用法的做了下总结,希望能够对大家有所帮助。

本项目中的lucene使用概述:在Portal项目中lucene的作用是对由cms(内容管理系统)生成的HTML文档进行索引和搜索。过程如下:首先需要把 HTML 文档转化成文本格式的(其中要用到htmlparser.jar和htmllexer.jar作用是获取网页中的内容),然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。整个过程可以概述为两个方面:索引和搜索

下面说说索引的重要性和lucene索引规则:索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。为什么索引这么重要呢,试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene采用的是一种称为反向索引(inverted index)的机制。反向索引就是说我们维护了一个词 / 短语表,对于这个表中的每个词 /短语,都有一个链表描述了有哪些文档包含了这个词 /短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。

1)下面是使用lucene来创建索引代码片段及其注释:

//生成索引书写器 参数一:索引文件存放路径
IndexWriter fsWriter = new IndexWriter(“/data/index/”, new StandardAnalyzer(), true);
//设置为混合索引格式
fsWriter.setUseCompoundFile(true);
//生成Document对象
Document doc = new Document();
//添加“title”字段的内容:第二个参数为标题。项目中需要从html中提取标题
doc.add(new Field("title", "welcome to tangula", Field.Store.YES, Field.Index.TOKENIZED));
//添加“content”字段的内容 第二个参数为内容。项目中需要从html中提取内容
doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED));
//将文档添加到索引中
writer.addDocument(doc);
//创建内存索引
Directory ramDirectory = new RAMDirectory();
IndexWriter ramWriter = new IndexWriter(ramDirectory,
new StandardAnalyzer(), true);
ramWriter.addDocument(doc);
ramWriter.close();
//将内存合并到本地磁盘索引
fsWriter.addIndexes(new Directory[] {ramDirectory});
//关闭索引
writer.close();

2)下面的代码是查询

//生成索引搜索器 参数一:索引存放的路径
IndexReader reader = IndexReader.open(indexHelper.getIndexPath());
Searcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer();
QueryParser parser = new QueryParser("contents", analyzer);
Query query = parser.parse(keyWord.trim());
Hits hits = searcher.search(query);

首先我们创建一个在指定文件目录上的IndexSearcher。
然后创建一个使用StandardAnalyzer作为分析器的QueryParser,它默认搜索的域是content。
接着我们用QueryParser来parse查询字串,生成一个Query。
然后利用这个Query去查找结果,结果以Hits的形式返回。
这个Hits对象包含一个列表,我们挨个把它的内容显示出来。

上面查询的时候用到了类QueryParser,现在说下这个类的用法:对于搜索引擎,很多情况下用户只需要一个输入框就要输入所有的查询条件(比如google),这时,QueryParser就派上用场了,他的作用就是把各种用户输入转为Query或者Query组,他把上面提到的Query的字符表示(Query.toString)转化为实际的Query对象,比如"wuzzy~"就会转换为FuzzyQuery,不过QueryParser用到了Analyzer,所以QueryParser parse过后的Query再toString未必和原来的一样.

Query额外的语法有:
分组:Groupping比如"(a AND b) or C",就是括号分组,很容易理解
FieldSelectiong
QueryParser的查询条件是对默认的Field进行的,它在QueryParser解析的时候编码指定,如果用户需要在查询条件中选用另外的Field,可以使用如下语法: fieldname:fielda,如果是多个分组,可以用fieldname:(fielda fieldb fieldc)表示.
*号问题
QueryParse默认不允许*号出现在开始部分,这样做的目的主要是为了防止用户误输入*来头导致严重的性能问题(会把所有记录读出)
boosting
通过hello^2.0可以对hello这个term进行boosting, QueryParser是一个准备好的,立即可以工作的帮助类,不过他还是提供了很多参数供程序员调整,首先,我们需要自己构造一个新的QueryParser,然后对他的各种参数来定制化

查询时其他相关类

搜索结果的处理:Hits对象
Hits对象是搜索结果的集合
主要有下面几个方法

length() ,这个方法记录有多少条结果返回(lazy loading)

doc(n) 返回第n个记录

id(in) 返回第n个记录的Document ID

score(n) 第n个记录的相关度(积分)
由于搜索的结果一般比较大,从性能上考虑,Hits对象并不会真正把所有的结果全部取回,默认情况下是保留前100个记录(对于一般的搜索引擎,100个记录足够了).
分页的处理
100条记录还是太多,我们多半会每页显示20条记录,然后分为若干页显示,对于分页,一般有两个办法

在session中保留indexreader对象和hit对象,翻页的时候提取内容

不使用session,每次都简单处理为重新查询
lucene推荐先使用第二个办法,即每次都重新查询,这样做的好处是简单方便,不需要考虑session的问题,lucene的查询效率也能保证每次查询时间不长,除非真正有了性能问题,否则不用考虑第一个办法。
缓存:RAMDirectory的用法
RAMDirectory对象很好用,通过它,我们可以把一个普通的index完全读取到内存中,用法如下:
RAMDirectory ramDir = new RAMDirectory(dir);
这样的ramdir效率自然比真正的文件系统快很多

Lucene的scoring算法
lucence查询的纪录默认按照相关度排序,这个相关度就是score,scoring的算法是比较复杂的,对于我们做应用的人似乎没有什么帮助,(先说一下Term:我的理解是Term为一个独立的查询词,用户输入的的查询通过各种分词,大小写处理(正规化),消除stopwords等)以后,会已Term为基本单位),几个关键参数稍微留意一下即可。
Term在文章中出现的频率量,包含同一个Term的文章的频率
field中的boosting参数

term的长度

term在文章中的数量
一般来说,这些参数我们都不可能去调整,如果你想了解更多,IndexSearcher还提供了一个explain方法,通过传入一个Query和document ID,你可以得到一个Explaination对象,他是对内部算法信息的简单封装,toString()一下就可以看到详细的说明

其他的各种query介绍

最普通的TermQueryTermQuery最普通,用Term t=new Term("contents","cap"); new TermQuery(t)就可以构造
TermQuery把查询条件视为一个key,要求和查询内容完全匹配,比如Field.Keyword类型就可以使用TermQuery
RangeQuery
RangeQuery表示一个范围的搜索条件,RangeQuery query = new RangeQuery(begin, end, included);
最后一个boolean值表示是否包含边界条件本身,用字符表示为"[begin TO end]"或者"{begin TO end}"
PrefixQuery
顾名思义,就是表示以某某开头的查询,字符表示为"something*"
BooleanQuery
这个是一个组合的Query,你可以把各种Query添加进去并标明他们的逻辑关系,添加条件用
public void add(Query query, boolean required, boolean prohibited)
方法,后两个boolean变量是标示AND or NOT三种关系
字符表示为" AND or NOT"或 "+ -" ,一个BooleanQuery中可以添加多个Query,如果超过setMaxClauseCount(int)的值(默认1024个)的话,会抛出TooManyClauses错误.
PhraseQuery表示不严格语句的查询,比如"red pig"要匹配"red fat pig","red fat big pig"等,PhraseQuery所以提供了一个setSlop()参数,在查询中,lucene会尝试调整单词的距离和位置,这个参数表示可以接受调整次数限制,如果实际的内容可以在这么多步内调整为完全匹配,那么就被视为匹配.在默认情况下slop的值是0,所以默认是不支持非严格匹配的,通过设置slop参数(比如"red pig"匹配"red fat pig"就需要1个slop来把pig后移动1位),我们可以让lucene来模糊查询.值得注意的是,PhraseQuery不保证前后单词的次序,在上面的例子中,"pig red"需要2个slop,也就是如果slop如果大于等于2,那么"pig red"也会被认为是匹配的.
WildcardQuery
使用?和*来表示一个或多个字母比如wil*可以匹配 wild ,wila ,wilxaaaa...,值得注意的是,在wildcard中,只要是匹配上的纪录,他们的相关度都是一样的,比如wilxaaaa和wild的对于wil*的相关度就是一样的.
FuzzyQuery
这个Query对中文没有什么用处,他能模糊匹配英文单词(前面的都是词组),比如fuzzy和wuzzy他们可以看成类似,对于英文的各种时态变化和复数形式,这个FuzzyQuery还算有用,匹配结果的相关度是不一样的.字符表示为 "fuzzy~"

搜索引擎lucene点滴相关推荐

  1. 一个例子学懂搜索引擎(lucene)

    http://www.vifir.com/html/20080827/1703937.html 一个例子学懂搜索引擎(lucene) 来源:javaeye 作者: phz50 2008-08-27 1 ...

  2. 搜索引擎lucene

    引用:http://baike.baidu.com/view/371811.htm Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它 ...

  3. 5分钟了解搜索引擎Lucene的原理

    场景 假设现在有10W+份word文档,让你做个web页面,给出关键词能快速搜索结果,你会怎么做?那至少有3种方案, 顺序扫描,每次检测文档中是否包含关键词,包含则加入结果列表,不包含继续查找下一个, ...

  4. 阿里P8架构师谈:开源搜索引擎Lucene、Solr、Sphinx等优劣势比较

    开源搜索引擎分类 1.Lucene系搜索引擎,java开发,包括: Lucene Solr Elasticsearch Katta.Compass等都是基于Lucene封装. 你可以想象Lucene系 ...

  5. 主流搜索引擎Lucene,Solr,ElasticSearch

    Lucene Lucene是一个Java全文搜索引擎,完全用Java编写.Lucene不是一个完整的应用程序,而是一个代码库和API,可以很容易地用于向应用程序添加搜索功能. 可扩展的高性能索引 在现 ...

  6. 开发自己的搜索引擎--Lucene 2.0+Heriterx(目录)

    第一篇  搜索引擎入门 第1章  搜索引擎与信息检索    1 1.1  搜索引擎的历史    1 1.1.1  萌芽:Archie.Gopher    1 1.1.2  起步:Robot(网络机器人 ...

  7. Elasticsearch - 搜索引擎Lucene

    1.1. Scaling Lucene 怎样在Lucene之上构建一个分布式.高度伸缩.接近实时的搜索引擎呢? 让我们回顾一下在搜索引擎(基于lucene)伸缩性这条路上都做了那些尝试,并且elast ...

  8. 搜索引擎Lucene(6):查询结果高亮及词频提取

    1.结果高亮 Lucene对高亮显示提供 了两种实现模式,Highlighter和FastVectorHighlighter.FastVectorHighlighter速度快,功能更完美.但其是有一定 ...

  9. 文本搜索引擎Lucene之filed详解和代码测试

    1.索引创建和查询过程 文档数据采集,一般是数据库的数据和爬虫获取的数据.而Lucene不提供信息采集的类库,需要自己编写一个爬虫程序实现信息采集,也可以通过一些开源软件实现信息采集,如下: Solr ...

最新文章

  1. mysql error 1231_解决ERROR 1231 (42000): Variable 'time_zone' can't
  2. Certificates, Identifiers Profiles创建总结
  3. android淡入淡出动画_在Android中淡入动画示例
  4. python会取代前端吗_大家说,python在不远的将来,会不会把java替代,为什么?
  5. YEAH!!距离拿回touch4倒计时:7days
  6. 电容式传感器位移性能试验报告_称重传感器的构成
  7. synchronized中重量级锁、偏向锁和轻量级锁的区别
  8. Java继承的基本概念及其限制(基础语法二)
  9. 诺顿企业版10.0 简体中文版
  10. MPEG-2 TS学习(一)MPEG-2 TS格式解析
  11. 【企业管理】价值评价的导向和原则
  12. 腾讯Node.js基础设施TSW正式开源 1
  13. Flutter系列(二)flutter项目打安装包
  14. 微信小程序云开发联表查询【聚合】
  15. 全新 Amazon RDS for MySQL 和 PostgreSQL 多可用区部署选项
  16. java 打开网页并运行脚本_各种浏览器开启JavaScript脚本方法
  17. starUML教程-用例图/类图
  18. 安卓【.9图】制作方法教程及技巧
  19. win7系统软件安装显示NSIS ERROR的解决方法
  20. 阿里云【7天实践训练营】进阶路线——Day3:阿里云云计算助理工程师认证(ACA)课程3 ~ 4章

热门文章

  1. python模拟鼠标 事件
  2. Echarts5.3.2可视化案例-应用篇
  3. 在flex 2中直接显示sprit
  4. 手把手教你升级Keil MDK的ARM编译器
  5. ZXing改横屏识别为竖屏识别
  6. 工作java工作总结
  7. IntelliJ IDEA 2021.1 关闭更新提醒
  8. signature=a335cd7040789f936f75c72e4ba37676,浅谈新教材Reading的整体教学
  9. Kafka 实战 (3):kafka安装部署·2
  10. ibatis mysql存储过程_分步详解 如何在iBatis中调用存储过程