全文检索引擎及工具

lucence

lucence是一个全文检索引擎。

lucence代码级别的使用步骤大致如下:

  1. 创建文档(org.apache.lucene.document.Document),并通过Document的add方法为其添加字段(lucence.document.Field)
  2. 创建lucence.index.IndexWriter,通过addDocument或addDocuments方法添加构建好的诸多Document
  3. 通过close方法关闭IndexWriter
  4. 创建索引搜索器lucence.search.IndexSearcher,需要传入索引仓库阅读器(lucenc.index.DirectoryReader)参数
  5. 通过search方法在搜索器上执行查询,参数是ucence.search.Query对象,通过查询解析器lucene.queryparser.classic.QueryParser的实例parse(String)方法来构建一个查询,QueryParser实例可以通过new标准解析器lucene.queryparser.flexible.standard.StandardQueryParser得到

中文文本索引构建及查询示例

(以下涉及的是6.4.2版本的lucene)

对中文文本构建索引时,不能使用StandardAnalyzer,它会把中文文本按单个字符分割,而非按词语分割,因而需要使用中文分词器,使用自定义的Analyzer。maven包org.apache.lucene:lucene-analyzers-common(由Lucene开发)带一个声称可以对CJK(Chinese、Japanese、Korean)文本分词的的分析器lucene.analysis.cjk.CJKAnalyzer,但其效果相当不好,几乎不可用,比如文本“白玫瑰的鲜花花语是什么?白色玫瑰花的花语:天真、纯洁、尊敬、谦卑,我足以与你相配。”的分词结果是“白玫, 玫瑰, 瑰的, 的鲜, 鲜花, 花花, 花语, 语是, 是什, 什么, 白色, 色玫, 玫瑰, 瑰花, 花的, 的花, 花语, 天真, 纯洁, 尊敬, 谦卑, 我足, 足以, 以与, 与你, 你相, 相配”。除此,smartcn(6.4.2版本maven包为org.apache.lucene:lucene-analyzers-smartcn:6.4.2中,其artifactId不同于版本3.6.2,后者为lucene-smartcn),是随lucene发布的用于处理中文文本的analyzer包,分词特点是词语分割得比较碎,比如上述文本的分词结果是“白, 玫瑰, 的, 鲜花, 花, 语, 是, 什么, 白色, 玫瑰花, 的, 花, 语, 天, 真, 纯洁, 尊敬, 谦卑, 我, 足以, 与, 你, 相, 配”

  • 以自带的smartcn分析包创建索引

    以下代码为scala语言所写,用到的东西不复杂,即使不清楚scala语法也不需要害怕,能看懂构建索引和查询的逻辑过程即可。

    代码满足这样的场景需求:假设文件$lucene.wikiIdTitle中有很多行,每行有两列,第一列是数字,第二列是字符串,他们以TAB字符分割,字符串代表一个文档的文本内容,数字代表文档的唯一编号,我们要为文档建立索引,查询时,给出关键词,输出文档唯一编号。

import org.slf4j.LoggerFactory
import com.typesafe.config.{ConfigFactory, _}
import org.apache.lucene
import lucene.index.{DirectoryReader, IndexWriter, IndexWriterConfig, _}
import lucene.document.{Field, FieldType, _}
import lucene.analysis.{CharArraySet, _}
import lucene.search.{IndexSearcher, _}
import lucene.store.{RAMDirectory, _}
import lucene.analysis.cn.smart.{SmartChineseAnalyzer, _}
import org.apache.lucene.index.IndexWriterConfig.OpenMode
import org.apache.lucene.queryparser.classic.QueryParser import scala.collection.convert.ImplicitConversions._
import scala.io.Source
import scala.util.{Failure, Success, Try} val log = LoggerFactory.getLogger(this.getClass) val conf = ConfigFactory.load("app") // 读取文件配置,对Java程序员来说相当于读 app.properties配置文件 log.info("creating lucene index for wikipedia titles...") // 保存lucene索引文件的目录,例如/path/to/index/
val indexDir = conf.getString("lucene.indexDir") log.debug(s"lucene index writing direcotry: $indexDir") import org.apache.lucene // 创建Directory对象,或创建写入硬盘的(FSDirectory)或直接在内存中操作的(RAMDirectory)。前者需要提供一个写入索引的目录参数。
// val idxDir = FSDirectory.open(java.nio.file.Paths.get(indexDir))
//小示例,直接在内存中操作算了
val idxDir = new RAMDirectory() val stopWordsFiles = conf.getString("lucene.stopWordsFiles") log.debug(s"lucene.stopWordsFiles: $stopWordsFiles") // “停用词”表,以过滤分词结果中没啥用处的停用词
val stopWords = stopWordsFiles.split(",").flatMap(f => Try {
if (f.trim.nonEmpty)
Source.fromFile(f).getLines()
else
Iterator.empty
} match {
case Success(x) => x
case Failure(e) =>
log.warn(s"error in loading stop words file: $f", e)
Iterator.empty
}).toList log.debug(s"stop words size: ${stopWords.length}") val smartcn = new SmartChineseAnalyzer(new CharArraySet(stopWords, true))
val iwConf = new IndexWriterConfig(smartcn)
// iwConf.setOpenMode(OpenMode.CREATE) // RAM中操作“重新创建”、“追加”几种写入模式都无所谓了
val indexWriter = new IndexWriter(idxDir, iwConf) // $lucene.wikiIdTitle表示文档集合文件的路径,示例中该文件内容如下
/*
1832186 义胆雄心
5376724 龙山洞
5420049 地下情人
5431949 里弗顿
5455483 长隆
5463308 阿尔伯特桥
5470979 冈田
5511092 肖迪奇站
5544906 莫农加希拉_(消歧义)
5553846 蓬莱洞
5553849 南山洞
5566592 开水
5566629 氧化锑
*/
val pgIdTtls=Source.fromFile(conf.getString("lucene.wikiIdTitle"))
.getLines()
.filter(ln => ln.nonEmpty)
.map(ln => {
val idTtl = ln.split("\t")
(idTtl(0), idTtl(1))
})
//pgIdTtls变量是一个二元组,对于Java程序员,不必了解什么是二元组,可想象成两列,第一列是唯一id,第二列是文本
pgIdTtls.foreach(e => {
import lucene.document._
//创建一个Document
val ldoc = new lucene.document.Document()
//由于第一列是文档唯一id,不需要被索引,但需要被保存,以便在检索到结果之后能“看到”这个id字段,不保存(.setStored(false))则即使被添加到document对象,在结果中也看不到该字段
val pageIdFieldType = new FieldType()
pageIdFieldType.setStored(true) // 要保存,因为我们想在结果中得到这个值
pageIdFieldType.setIndexOptions(lucene.index.IndexOptions.NONE) //别在id字段上做索引
// 事实上,为了性能,可以把pageIdFieldType移到循环外,示例中放在这里是为了让FieldType的出现看起来更合理
// 为文档创建字段,名为pageId(字段名随意取,不过在检索结果中提取时你得记得这个字段的名字),值为第一列(即文档唯一编号)
val piFld = new lucene.document.Field("pageId", e._1, pageIdFieldType)
ldoc.add(piFld)
//把文档的文本内容添加到title字段,要保存(Field.Store.YES)
ldoc.add(new lucene.document.TextField("title", e._2, Field.Store.YES))
indexWriter.addDocument(ldoc) // 写入index
}) //indexWriter.close() // 如果用硬盘写入(FSDirectory.open方式),要记得关闭 val searcher = new IndexSearcher(DirectoryReader.open(indexWriter))
// 如果是读取某个目录下的index,则应该用
// val searcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(java.nio.file.Paths.get("/path/to/index/")))) import lucene.queryparser.classic._ // 在title字段上搜索
val queryParser = new QueryParser("title", smartcn)
// 搜索“南山洞”
val query = queryParser.parse("南山洞") //
val hitPageIdTitles = searcher
.search(query, 30) // 最多返回30个结果,还有更多我也不想要了(类似SQL的limit 30
.scoreDocs.map(searcher doc _.doc)
.map(d => (d.get("pageId"), d.get("title"))) //上一scala语句对java程序员来说理解起来可能稍微有点费力,翻译为java,是这样的
/*
ScoreDoc[] scoreDocs=searcher.search(query,30).scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
//得到检索到的Document
org.apache.lucene.document.Document d= searcher.doc(scoreDoc.doc);
// 从Document中获取文档编号和文本内容
System.out.println(d.get("pageId")+", "+d.get("title"))
}
*/
//检索到两个结果(5553849,南山洞), (5376724,龙山洞)
  • 编写Analyzer子类,实现使用自定义分词工具分词

    //TODO

solr

solr是一个构建在lucence之上的应用服务器,属于一个全文检索工具,以http提供服务。

全文检索引擎及工具 Lucene Solr的更多相关文章

  1. Solr全文检索引擎配置及使用方法

    介绍 Solr是一款开源的全文检索引擎,基于lucene.拥有完善的可配置功能界面.具有丰富的查询语言,可扩展,可优化. 下载安装 进入solr官网下载包(这里我使用的版本是8.0) http://w ...

  2. lucene&solr学习——solr学习(一)

    1.什么是solr solr是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文检索服务器.Solr提供了比lucene风味丰富的查询语言,同时实现了可配置,可扩展,并对索 ...

  3. Apache Lucene(全文检索引擎)—创建索引

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

  4. 全文检索引擎 Solr 部署与基本原理

    全文检索引擎 Solr 部署与基本原理 搜索引擎Solr环境搭建实例 关于 solr , schema.xml 的配置说明 全文检索引擎Solr系列-–全文检索基本原理 一.搜索引擎Solr环境搭建实 ...

  5. Lucene:基于Java的全文检索引擎简介

    Lucene:基于Java的全文检索引擎简介 Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引/检索引擎--Lucene Lucene不是一个完整的全文索引应用,而是是一个用J ...

  6. Lucene 全文检索引擎

    Apache Lucene PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程, 仅供各位程序猿们参考,这 ...

  7. Lucene:基于Java的全文检索引擎简介 (zhuan)

    http://www.chedong.com/tech/lucene.html ********************************************** Lucene是一个基于Ja ...

  8. [摘]全文检索引擎Solr系列—–全文检索基本原理

    原文链接--http://www.importnew.com/12707.html 全文检索引擎Solr系列—–全文检索基本原理 2014/08/18 | 分类: 基础技术, 教程 | 2 条评论 | ...

  9. 全文检索(Lucene&Solr)

    全文检索(Lucene&Solr) 1)什么是全文检索?为什么需要全文检索? 结构化数据(mysql等)方便查询,而非结构化数据(如多篇文章)是难以查询到自己需要的,所以要使用全文检索. 全文 ...

随机推荐

  1. Linux - docker基础

    目录 Linux - docker基础 docker的概念 docker安装流程 docker基本命令学习 docker 的 hello docker 运行一个ubuntu容器 Docker与Cent ...

  2. PAT 1113 Integer Set Partition

    Given a set of N (>1) positive integers, you are supposed to partition them into two disjoint set ...

  3. 解析 XML 数据

    在几个月前我有做过这样的记录,其目的是避免解析 XML 时手工编写太多的代码,造成重复的体力劳动.后来经过一番资料的查找,我发现其实并没有必要做这样的工具,因为 C# 已经为我们提供了更好的解决方案了 ...

  4. 【Codeforces Global Round 1 E】Magic Stones

    [链接] 我是链接,点我呀:) [题意] 你可以把c[i]改成c[i+1]+c[i-1]-c[i] (2<=i<=n-1) 问你能不能把每一个c[i]都换成对应的t[i]; [题解] d[ ...

  5. map put

    public class test { static Map<String, Map<String, Integer>> mapB = new HashMap<Strin ...

  6. BZOJ——T 1801: [Ahoi2009]chess 中国象棋

    http://www.lydsy.com/JudgeOnline/problem.php?id=1801 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit:  ...

  7. VB.NET机房收费 &amp; 抽象工厂模式

    学习设计模式的时候,提到了一个专门訪问数据库的模式-抽象工厂模式,记得当时举样例理解的时候并未设计到数据库,仅仅是大概了了解了一下,如今对于机房收费系统涉及到了数据库的管理,借此机会好好学习一下.用常 ...

  8. 【JavaScript】正則表達式

    正則表達式,也不是第一次与它见面了.在我们学习ASP.NET视频的时候,验证控件的那个实例中.就有提到过它. 那个时候.都是在控件的属性中自己设置的,用的原理就是正則表達式,当时得感觉就是方便,强大, ...

  9. Oracle 堵塞(blocking blocked)

    堵塞是DBA常常碰到的情形,尤其是不良的应用程序设计的堵塞将导致性能严重下降直至数据库崩溃. 对DBA而言,有必要知道怎样定位到当前系统有哪些堵塞,究竟谁是堵塞者,谁是被堵塞者.本文对此给出了描写叙述 ...

  10. [odroid-pc] ubuntu12.04 android4.0移植到odroid-pc过程

    參考:http://blog.csdn.net/sunnybeike/article/details/8098349 odroid  prebuilt版 img下载地址:tag=ODROID-PC&q ...