Lucene&Solr(之一)-全文索引、入门程序
2017-04-27 15:06
363 查看
什么是全文检索
1、生活中的数据类型分成:a、结构化数据:类型固定、格式固定、有限长度的数据。如数据库中的数据
b、非结构化数据:格式不固定、长度不固定的数据。如txt文档、word文档和excel文档、pdf等。
2、数据查询:
结构化数据查询:一般使用sql进行查询( Structure Query Language )。
非结构化数据查询:
a、通过顺序检索,一个一个看……
b、自己写程序,通过IO流读取,匹配字符串。
c、把非结构化数据变成结构化数据。
如:将一段英文文本根据空格拆分,得到单词列表,记录下单词和文本的关系。
查询时只需要查询单词列表,根据单词和文件的对应关系找到文件。基于单词列表创建索引提高查询速度。
这个过程就叫全文检索。
3、全文检索:
这种先建立索引,再对索引进行搜索的过程就叫全文检索。一次创建多次查询。
Lucene实现全文检索的流程
Lucene可以实现全文检索,Lucene是apache旗下一个开源的全文检索引擎工具包。全文检索的应用场景:
1、搜索引擎:百度一下等
2、电商搜索:淘宝、天猫等
3、论坛搜索:论坛、微博等
Lucene实现全文检索的流程
1、创建索引
原始文档:基于哪些内容进行搜索。如果是文件搜索,要查询的文件就是原始文档;
搜索引擎:整个互联网的网页内容
电商搜索:所有商品数据
a、获得原始文档
如果是文件:使用IO流读取文件内容
搜索引擎:使用爬虫抓取网页
在internet上采集信息的软件通常称为爬虫或蜘蛛,也成网络机器人。爬取互联网的网页,原理其实是模拟浏览器。
Heritrix:java开发的开源的爬虫,用户可以自己使用它从网上抓取资源,良好的可扩展性,方便用户自定逻辑。
Nutch:apache旗下爬虫程序。lucene&solr都是apache旗下的。
jsoup:java的解析html工具包,可通过DOM、CSS以及类似于JQuery的操作方法取出和操作数据。
电商网站:查询数据库。
b、创建文档对象。每个原始文档对应一个文档对象Document对象。
向Document中添加field,field叫做域。每个field中保存原始文档的一个属性。
每个Document可以有多个field,不同的Document可以有不同的field,同一个Document可以有相同的Field(域
名和域值都相同)
每个文档都有唯一id。
c、分析文档内容
1、先对文档内容根据空格进行字符串拆分,得到一个单词列表。
2、去除标点符号,去除停用词,转换成小写。
最终得到一个词汇单元流(理解为一个一个的单词)。
基于词汇单元流创建索引。索引是一个提高查询速度的数据结构。
d、创建索引库
把索引和文档对象写入磁盘。
索引部分、文档部分、关键字和文档之间的对应关系。
每个单词叫做term,term包括两部分内容,一个关键字和关键字所在的域。
如文件名中包含apache和文件内容中包含的apache是不同的term。
2、查询索引
a、用户查询接口用户输入查询条件的地方。如百度搜索框
b、接收查询条件
查询对象中包含要搜索的域和要搜索的内容。
lucene基本查询语法:
域的名称:关键字---fileName:lucene
c、查询索引
查询索引库中的索引部分,在某个域上查询关键字。找到关键字得到文档id列表。
d、渲染结果
1、根据id获取文档对象。
2、从文档的field中取内容,展示给用户。
3、关键字高亮显示、相关度排序、分页等效果。
入门程序
1、jar包lucene核心core文件夹下jar、analyzer-common包、common-io包
2、创建索引库的实现步骤:
1)创建java工程
2)导入lucene相关包
3)创建Directory对象,索引库保存的目录
4)创建IndexWriterConfig对象,参数1:lucene的版本号,参数2:分析器对象,使用标准分析器(英文文本)
5)创建IndexWriter对象,传入IndexWriterConfig对象
6)使用IO流,读取文件信息
7)对应每个文件创建一个Document对象
8)创建field对象,向文档对象中添加域
9)把文档对象写入索引库
10)关闭流
代码实现:
@Test public void createIndex() throws Exception{ // 3)创建Directory对象,索引库保存的目录 //Directory directory = new RAMDirectory(); // 索引库存放位置:内存 Directory directory = FSDirectory.open(new File("F:\\index")); // 4)创建IndexWriterConfig对象,参数1:lucene的版本号,参数2:分析器对象,使用标准分析器(英文文本) Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); // 5)创建IndexWriter对象,传入IndexWriterConfig对象 IndexWriter writer = new IndexWriter(directory, config); File file = new File("E:\\就业\\课程\\Lucene&Solr\\00.参考资料\\searchsource"); for (File f : file.listFiles()) { // 6)使用IO流,读取文件信息 String fileName = f.getName(); String fileContent = FileUtils.readFileToString(f); String filePath = f.getPath(); long fileSize = FileUtils.sizeOf(f); // 7)对应每个文件创建一个Document对象 Document document = new Document(); // 8)创建field对象,向文档对象中添加域 // 参数1:域的名称,参数2:域的内容,参数3:是否存储 Field field1 = new TextField("name", fileName, Store.YES); Field field2 = new TextField("content", fileContent, Store.YES); Field field3 = new TextField("path", filePath, Store.YES); Field field4 = new TextField("size", fileSize + "", Store.YES); document.add(field1); document.add(field2); document.add(field3); document.add(field4); // 9)把文档对象写入索引库 writer.addDocument(document); } // 10)关闭流 writer.close(); }
3、查询索引的实现步骤:
1)打开索引库,以读的方式打开。创建IndexReader对象,需要创建Document对象
2)创建IndexSearcher对象,传入IndexReader对象。
3)创建一个查询对象,Query的子类TermQuery,传入两个参数:要搜索的域和要查询的内容
4)执行查询,得到一个文档id列表
5)遍历列表根据文档的id取文档对象
6)从域中取内容,并打印
7)关闭流
代码实现:
@Test public void searchIndex() throws Exception { // 1)打开索引库,以读的方式打开。创建IndexReader对象,需要创建Document对象 Directory directory = FSDirectory.open(new File("F:\\index")); IndexReader reader = DirectoryReader.open(directory); // 2)创建IndexSearcher对象,传入IndexReader对象。 IndexSearcher searcher = new IndexSearcher(reader); // 3)创建一个查询对象,Query的子类TermQuery,传入两个参数:要搜索的域和要查询的内容 Query query = new TermQuery(new Term("name", "apache")); // 4)执行查询,得到一个文档id列表 //参数1:查询对象,参数2:查询结果返回的最大记录数,返回最多10个 TopDocs topDocs = searcher.search(query, 10); // 查询的总记录数 System.err.println("本次查询结果总记录数:" + topDocs.totalHits); // 5)遍历列表根据文档的id取文档对象 for (ScoreDoc scoreDoc : topDocs.scoreDocs) { // 去文档id int id = scoreDoc.doc; // 根据id去文档对象 Document document = searcher.doc(id); // 6)从域中取内容,并打印 System.out.println("=========================================================================================="); System.out.println(document.get("name")); System.out.println(document.get("path")); System.out.println(document.get("size")); //System.out.println(document.get("content")); } // 7)关闭流 reader.close(); }
TopDocs
lucene搜索结果可通过TopDocs遍历,提供属性:totalHits
:匹配搜索条件的总记录数
scoreDocs
:相关度高的顶部匹配记录,长度<=search方法指定的n。
分析器
在使用分析器之前,需要先查看分析器的分词效果。每个分析器对象,都有个tokenStream的方法,返回一个TokenStream对象,通过查看TokenStream对象中的内容,分词效果。
使用方法:
1)创建Analyzer对象
2)调用Analyzer的tokenStream,得到TokenStream对象,参数就是待分析的文本。
3)设置一个引用,通过这个引用查看分词效果
4)调用TokenStream的reset方法。初始化这个引用
5)循环遍历TokenStream打印结果。
代码实现:
@Test public void testTokenStream() throws Exception { // 创建一个标准分词器 Analyzer analyzer = new StandardAnalyzer(); // 获取TokenStream对象 TokenStream tokenStream = analyzer.tokenStream("此处写域名", "The Spring Framework provides a comprehensive programming and configuration model."); // 3)设置一个引用,通过这个引用查看分词效果 CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); // 4)调用TokenStream的reset方法。初始化这个引用 tokenStream.reset(); // 5)循环遍历TokenStream打印结果。 while(tokenStream.incrementToken()) { System.out.println(charTermAttribute.toString()); } }
中文分析器
推荐第三方:这里使用 IKAnalyzer
1、添加jar包到工程中。
2、第三方的配置文件、扩展词典文件、停用字词典文件配置到classpath下
注意:必须保证词典文件编码格式为 utf-8
代码实现:
@Test public void testTokenStream() throws Exception { Analyzer analyzer = null; // 创建一个标准分词器 //analyzer = new StandardAnalyzer(); // 二分法分词 //analyzer = new CJKAnalyzer(); //扩展性差 //analyzer = new SmartChineseAnalyzer(); // 第三方 IK-analyzer analyzer = new IKAnalyzer(); // 获取TokenStream对象 String str = "Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,"; TokenStream tokenStream = analyzer.tokenStream("此处写域名", str); // 3)设置一个引用,通过这个引用查看分词效果 CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); // 4)调用TokenStream的reset方法。初始化这个引用 tokenStream.reset(); // 5)循环遍历TokenStream打印结果。 while(tokenStream.incrementToken()) { System.out.println(charTermAttribute.toString()); } }
相关文章推荐
- Solr入门之Lucene&Solr临近查询之SpanQuery
- lucene&solr从入门到精通-----创建索引,写到索引库
- lucene&solr从入门到精通-----删除,修改,查询
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<Oracle_查询>(三十四)
- solr&lucene3.6.0源码解析(一)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<JDBC>(二十四)
- lucene&solr大盘点
- lucene&IKAnalyzer入门实例
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<DOM解析>(三十二)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<SQL_Server_常用查询>(二十二)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<SQL_Server_视图_函数_存储过程_触发器等>(二十三)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<数据库连接配置>(二十八)
- GDI&GDI+程序入门
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<反射>(二十九)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<javascript>(三十)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<tomcat>(二十五)
- lucene & solr optimize 索引后结果与平台有点关系
- Berkeley DB Xml 入门系列之一: 简介与"query"示例程序详解
- Lucene & Solr【转载】
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<servlet_文件下载>(二十七)