文档章节

Lucene初探

propagator
 propagator
发布于 2017/06/14 20:02
字数 1283
阅读 57
收藏 0

最近因工作需要研究了一下lucene搜索引擎核心,初步了解了其运行机制。Lucene搜索引擎分为两大块,首先对要搜索的内容建立索引,然后在此基础上进行搜索。

 

Lucene可在如下网址下载:

http://mirror.bit.edu.cn/apache/lucene/

下载其中的Lucene-x.x.x.zip即可。解压后可获得编译好的jar包,在自己工程中引用相应的jar包即可。

 

Lucene的官方文档可在其官网上找到

https://lucene.apache.org/core/

但并没有给出很多例子和讲解,只给出了api的说明和两个样例源文件,一个用来索引,另一个用来搜索。

 

为了简单快速了解Lucene,自己写了一个例子,先贴代码

import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;

public class SimpleDemo {
	public static void main(String[] args) throws Exception {
	    Analyzer analyzer = new SmartChineseAnalyzer();
	    //Analyzer analyzer = new StandardAnalyzer();

	    // Store the index in memory:
	    Directory directory = new RAMDirectory();
	    // To store an index on disk, use this instead:
	    //Directory directory = FSDirectory.open("/tmp/testindex");
	    IndexWriterConfig config = new IndexWriterConfig(analyzer);
	    IndexWriter iwriter = new IndexWriter(directory, config);

	    Document doc = new Document();
	    String queryString = "因为";
	    String text = "请把悲伤留下,带着欢乐离去,因为我爱你。";

	    doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
	    iwriter.addDocument(doc);
	    
	    Path filePath = Paths.get("F:\\Temp\\Test.txt");
	    InputStream stream = Files.newInputStream(filePath);
        // To show the features manually split a document into several
	    //doc.add(new TextField("fieldname", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));
	    InputStreamReader m_isr = new InputStreamReader(stream, StandardCharsets.UTF_8);
	    BufferedReader m_br = new BufferedReader(m_isr);
	    String data = null;
	    int idx = 0;
	    while((data=m_br.readLine())!=null){
	    	idx += 1;
	    	doc.clear();
	    	doc.add(new TextField("fieldname", data, Field.Store.YES));
	    	iwriter.updateDocument(new Term("key"+idx+"", doc.toString()), doc);
	    }
	    iwriter.close();
	    
	    
	    // Now search the index:
	    DirectoryReader ireader = DirectoryReader.open(directory);
	    IndexSearcher isearcher = new IndexSearcher(ireader);
	    // Parse a simple query that searches for "text":
	    QueryParser parser = new QueryParser("fieldname", analyzer);
	    Query query = parser.parse(queryString);
	    TopDocs result = isearcher.search(query, 200);
	    ScoreDoc[] hits = result.scoreDocs;
	    System.out.println("matches: " + result.totalHits);
	    // Iterate through the results:
	    for (int i = 0; i < hits.length; i++) {
	      Document hitDoc = isearcher.doc(hits[i].doc);
	      System.out.println("score="+hits[i].score+", doc["+i+"]: "+hitDoc.get("fieldname"));
	    }
	    ireader.close();
	    directory.close();
	    
	    System.out.println("searching complete successfully!");
	}
}

 

接下来逐段说明一下。

	    Analyzer analyzer = new SmartChineseAnalyzer();
	    //Analyzer analyzer = new StandardAnalyzer();

	    // Store the index in memory:
	    Directory directory = new RAMDirectory();
	    // To store an index on disk, use this instead:
	    //Directory directory = FSDirectory.open("/tmp/testindex");
	    IndexWriterConfig config = new IndexWriterConfig(analyzer);
	    IndexWriter iwriter = new IndexWriter(directory, config);

这一段先对用到的基本变量做了定义和初始化。Analyzer是文本分析器,用来对文本进行分词,建立标记(token)等。directory顾名思义表示文件夹,用来保存文档。此处用来保存建立的索引,如注释说明的,因为是样例程序,采用内存来保存索引文件,如果是大规模的数据,需要改为用硬盘保存索引文件。IndexWriterConfig和IndexWriter用来初始化索引写入器,并将索引写入directory中。

 

	    Document doc = new Document();
	    String queryString = "因为";
	    String text = "请把悲伤留下,带着欢乐离去,因为我爱你。";

	    doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
	    iwriter.addDocument(doc);
	    
	    Path filePath = Paths.get("F:\\Temp\\Test.txt");
	    InputStream stream = Files.newInputStream(filePath);
        // To show the features manually split a document into several
	    //doc.add(new TextField("fieldname", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));
	    InputStreamReader m_isr = new InputStreamReader(stream, StandardCharsets.UTF_8);
	    BufferedReader m_br = new BufferedReader(m_isr);
	    String data = null;
	    int idx = 0;
	    while((data=m_br.readLine())!=null){
	    	idx += 1;
	    	doc.clear();
	    	doc.add(new TextField("fieldname", data, Field.Store.YES));
	    	iwriter.updateDocument(new Term("key"+idx+"", doc.toString()), doc);
	    }
	    iwriter.close();

这一段做了两件事,1是把一段字符串加入document中,放入directory;2是把一个文本文件的每一行作为一个document,放入directory。其中,每个文档(document)只有一个字段,即fieldname,原则上每个文档可以有很多字段,这些字段的名称可以自己定义,比如这里就定义为fieldname。如果把待搜索的文件作为一个document,那么原则上可以把文件名,路径,创建时间,修改时间,文件大小等都作为一个字段,以方便未来对不同的字段进行搜索。注意每次document的更新/修改都被添加/更新到directory中(利用iwriter.addDocument和iwriter.updateDocument来实现),从而保证directory记录了所有最新的索引信息。

 

	    // Now search the index:
	    DirectoryReader ireader = DirectoryReader.open(directory);
	    IndexSearcher isearcher = new IndexSearcher(ireader);
	    // Parse a simple query that searches for "text":
	    QueryParser parser = new QueryParser("fieldname", analyzer);
	    Query query = parser.parse(queryString);
	    TopDocs result = isearcher.search(query, 200);
	    ScoreDoc[] hits = result.scoreDocs;
	    System.out.println("matches: " + result.totalHits);
	    // Iterate through the results:
	    for (int i = 0; i < hits.length; i++) {
	      Document hitDoc = isearcher.doc(hits[i].doc);
	      System.out.println("score="+hits[i].score+", doc["+i+"]: "+hitDoc.get("fieldname"));
	    }
	    ireader.close();
	    directory.close();

这一段开始,对刚才索引的信息进行检索。首先打开保存索引信息的directory,创建IndexSearcher,然后定义请求,此处为检索所有fieldname字段中的queryString(“因为”)字符串。isearcher.search(query, 200)表示搜索前200条信息,搜索结果保存在ScoreDoc数组hits中。需要注意的是,实际上hits中给出的是真实文档的编号,要得到真正的文档内容,需要利用isearcher.doc函数将该编号转换成对应的document。另外每个文档对关键字queryString的匹配度保存在hits[i].score中,hits中的结果是按照匹配度从高到低的顺序排的。

 

虽然上面的例子已经可以对中文进行检索(利用SmartChineseAnalyzer),但实际上,Lucene目前对中文的支持还不太好。为了改善中文检索性能,还需要对Lucene进行一些改造,这部分内容将在后续的博文中给出。

© 著作权归作者所有

propagator
粉丝 8
博文 40
码字总数 45924
作品 0
昆明
私信 提问
Solr初探(3)——配置IK分词器

Solr配置第三方分词器也是十分简单,这里以IK分词器为例。点击下载我自编译的,支持到 JDK 1.8 + Lucene 6.6.2。 Step1: 将的jar包放到目录下。 Step2:将IK分词器的配置文件放到文件夹下,...

yuanlaijike
2018/04/10
0
0
Apache Lucene-使用简单介绍

首先呢,学习任何一门新的亦或是旧的开源技术,百度其中一二是最简单的办法,先了解其中的大概,思想等等。这里就贡献一个讲解很到位的ppt。已经被我转成了PDF,便于搜藏。   其次,关于第...

LANTIANFEIYING
2016/10/19
0
0
Elasticsearch初探(1)——基本介绍与环境搭建

版权声明:本文版权归Jitwxs所有,欢迎转载,但未经作者同意必须保留原文链接。 https://blog.csdn.net/yuanlaijike/article/details/82966110 一、Elasticsearch简介 1.1 什么是Elasticsear...

Jitwxs
2018/10/08
0
0
WinForms UI控件初探:Grid Control 、Data Grid、TreeList

Grid Control 、Data Grid、Spreadsheet、Data Editor、TreeList: 超乎你想象!WinForms Grid Control处理100万行数据到底有多快? WinForms界面控件初探:处理速度飞快的WinForms Data Gri...

百mumu
2016/07/13
31
0
提取文件内容其实很简单 – Apache Tika 初探

Apache宣布几个新的顶级项目,其中有一个就是Tika,一个文件内容提取的工具包,他支持的格式很多(详细): Tika整体代码设计非常优雅,通过Tika类目发布给用户,并将相关接口包装成简单的方法...

小编辑
2010/05/25
4.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

分布式协调服务zookeeper

ps.本文为《从Paxos到Zookeeper 分布式一致性原理与实践》笔记之一 ZooKeeper ZooKeeper曾是Apache Hadoop的一个子项目,是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它...

ls_cherish
今天
4
0
redis 学习2

网站 启动 服务端 启动redis 服务端 在redis 安装目录下 src 里面 ./redis-server & 可以指定 配置文件或者端口 客户端 在 redis 的安装目录里面的 src 里面 ./redis-cli 可以指定 指定 连接...

之渊
昨天
2
0
Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
昨天
4
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
昨天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
昨天
24
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部