lucene初体验

来源:互联网 发布:seo原创软文代写兼职 编辑:程序博客网 时间:2024/05/23 23:06

通过学习之后做一下总结吧:

什么是lucene

   Lucene是apache旗下的顶级项目,是一个全文检索工具包

   Lucene就是一个可以创建全文检索引擎系统的一堆jar包.可以使用它来构建全文检索引擎系统,但是它不能独立运行。

Lucene应用领域

1.互联网全文检索引擎(比如百度,  谷歌,  必应)

2.站内全文检索引擎(淘宝, 京东搜索功能)

3.优化数据库查询(因为数据库中使用like关键字是全表扫描也就是顺序扫描算法,查询慢) 

Lucene下载官方网站:http://lucene.apache.org/ 

Lucene结构

  索引:

域名:词  这样的形式,

它里面有指针执行这个词来源的文档

 

  索引库

放索引的文件夹(这个文件夹可以自己随意创建,在里面放索引就是索引库)

Term词元: 就是一个词, 是lucene中词的最小单位

  文档:

Document对象,一个Document中可以有多个Field域对象,Field域对象中是key   value键值对的形式:有域名和域值,一个document就是数据库表中的一条记录, 一个Filed域对象就是数据库表中的一行一列。这是一个通用的存储结构.

 

创建索引和所有时所用的分词器必须一致

 

域的详细介绍

是否分词:

       分词的作用是为了索引

         需要分词: 文件名称, 文件内容

         不需要分词: 不需要索引的域不需要分词,还有就是分词后无意义的域不需要分词

                          比如: id, 身份证号

 

是否索引:

      索引的的目的是为了搜索.

         需要搜索的域就一定要创建索引,只有创建了索引才能被搜索出来

         不需要搜索的域可以不创建索引

         需要索引: 文件名称, 文件内容, id, 身份证号等

         不需要索引: 比如图片地址不需要创建索引,e:\\xxx.jpg,因为根据图片地址搜索无意义

是否存储:

     存储的目的是为了显示.

       是否存储看个人需要,存储就是将内容放入Document文档对象中保存出来,会额外占用磁盘空间, 如果搜索的时候需要马上显示出来可以放入document中也就是要存储,这样查询显示速度快, 如果不是马上立刻需要显示出来,则不需要存储,因为额外占用磁盘空间不划算.


域的各种类型

Field类

数据类型

Analyzed

是否分析

Indexed

是否索引

Stored

是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

YN

这个Field用来构建一个字符串Field,但是不会进行分析,会将整个串存储在索引中,比如(订单号,姓名等)

是否存储在文档中用Store.YES或Store.NO决定

LongField(FieldName, FieldValue,Store.YES)

Long

Y

Y

YN

这个Field用来构建一个Long数字型Field,进行分析和索引,比如(价格)

是否存储在文档中用Store.YES或Store.NO决定

StoredField(FieldName, FieldValue)

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field

不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

 

字符串

Y

Y

YN

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.


需要源码的点击这个链接下载项目源码下载

package cn.itheima.lucene;import java.io.File;import java.util.ArrayList;import java.util.List;import org.apache.commons.io.FileUtils;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.TextField;import org.apache.lucene.document.Field.Store;import org.apache.lucene.document.LongField;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.index.Term;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;import org.junit.Test;import org.wltea.analyzer.lucene.IKAnalyzer;public class IndexManagerTest {@Testpublic void testIndexCreate() throws Exception{//创建文档列表,保存多个DocuemntList<Document> docList = new ArrayList<Document>();//指定文件所在目录File dir = new File("E:\\01传智课程\\黑28期0523\\Lucene&Solr\\01.参考资料\\searchsource"); //循环文件夹取出文件for(File file : dir.listFiles()){//文件名称String fileName = file.getName();//文件内容String fileContext = FileUtils.readFileToString(file);//文件大小Long fileSize = FileUtils.sizeOf(file);//文档对象,文件系统中的一个文件就是一个Docuemnt对象Document doc = new Document();//第一个参数:域名//第二个参数:域值//第三个参数:是否存储,是为yes,不存储为no/*TextField nameFiled = new TextField("fileName", fileName, Store.YES);TextField contextFiled = new TextField("fileContext", fileContext, Store.YES);TextField sizeFiled = new TextField("fileSize", fileSize.toString(), Store.YES);*///是否分词:要,因为它要索引,并且它不是一个整体,分词有意义//是否索引:要,因为要通过它来进行搜索//是否存储:要,因为要直接在页面上显示TextField nameFiled = new TextField("fileName", fileName, Store.YES);//是否分词: 要,因为要根据内容进行搜索,并且它分词有意义//是否索引: 要,因为要根据它进行搜索//是否存储: 可以要也可以不要,不存储搜索完内容就提取不出来TextField contextFiled = new TextField("fileContext", fileContext, Store.NO);//是否分词: 要, 因为数字要对比,搜索文档的时候可以搜大小, lunene内部对数字进行了分词算法//是否索引: 要, 因为要根据大小进行搜索//是否存储: 要, 因为要显示文档大小LongField sizeFiled = new LongField("fileSize", fileSize, Store.YES);//将所有的域都存入文档中doc.add(nameFiled);doc.add(contextFiled);doc.add(sizeFiled);//将文档存入文档集合中docList.add(doc);}//创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词Analyzer analyzer = new IKAnalyzer();//指定索引和文档存储的目录Directory directory = FSDirectory.open(new File("E:\\dic"));//创建写对象的初始化对象IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);//创建索引和文档写对象IndexWriter indexWriter = new IndexWriter(directory, config);//将文档加入到索引和文档的写对象中for(Document doc : docList){indexWriter.addDocument(doc);}//提交indexWriter.commit();//关闭流indexWriter.close();}@Testpublic void testIndexDel() throws Exception{//创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词Analyzer analyzer = new IKAnalyzer();//指定索引和文档存储的目录Directory directory = FSDirectory.open(new File("E:\\dic"));//创建写对象的初始化对象IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);//创建索引和文档写对象IndexWriter indexWriter = new IndexWriter(directory, config);//删除所有//indexWriter.deleteAll();//根据名称进行删除//Term词元,就是一个词, 第一个参数:域名, 第二个参数:要删除含有此关键词的数据indexWriter.deleteDocuments(new Term("fileName", "apache"));//提交indexWriter.commit();//关闭indexWriter.close();}/** * 更新就是按照传入的Term进行搜索,如果找到结果那么删除,将更新的内容重新生成一个Document对象 * 如果没有搜索到结果,那么将更新的内容直接添加一个新的Document对象 * @throws Exception */@Testpublic void testIndexUpdate() throws Exception{//创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词Analyzer analyzer = new IKAnalyzer();//指定索引和文档存储的目录Directory directory = FSDirectory.open(new File("E:\\dic"));//创建写对象的初始化对象IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);//创建索引和文档写对象IndexWriter indexWriter = new IndexWriter(directory, config);//根据文件名称进行更新Term term = new Term("fileName", "web");//更新的对象Document doc = new Document();doc.add(new TextField("fileName", "xxxxxx", Store.YES));doc.add(new TextField("fileContext", "think in java xxxxxxx", Store.NO));doc.add(new LongField("fileSize", 100L, Store.YES));//更新indexWriter.updateDocument(term, doc);//提交indexWriter.commit();//关闭indexWriter.close();}}

//////////////////////////////////////////////////////////////////////////////////////

package cn.itheima.lucene;import java.io.File;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.Term;import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.search.BooleanClause.Occur;import org.apache.lucene.search.BooleanQuery;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.MatchAllDocsQuery;import org.apache.lucene.search.NumericRangeQuery;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.junit.Test;import org.wltea.analyzer.lucene.IKAnalyzer;public class IndexSearchTest {@Testpublic void testIndexSearch() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();//创建查询对象,第一个参数:默认搜索域, 第二个参数:分词器//默认搜索域作用:如果搜索语法中指定域名从指定域中搜索,如果搜索时只写了查询关键字,则从默认搜索域中进行搜索QueryParser queryParser = new QueryParser("fileContext", analyzer);//查询语法=域名:搜索的关键字Query query = queryParser.parse("fileName:web");//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(query, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}@Testpublic void testIndexTermQuery() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();//创建词元:就是词,   Term term = new Term("fileName", "apache");//使用TermQuery查询,根据term对象进行查询TermQuery termQuery = new TermQuery(term);//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(termQuery, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}@Testpublic void testNumericRangeQuery() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();//根据数字范围查询//查询文件大小,大于100 小于1000的文章//第一个参数:域名      第二个参数:最小值,  第三个参数:最大值, 第四个参数:是否包含最小值,   第五个参数:是否包含最大值Query query = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(query, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}@Testpublic void testBooleanQuery() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();//布尔查询,就是可以根据多个条件组合进行查询//文件名称包含apache的,并且文件大小大于等于100 小于等于1000字节的文章BooleanQuery query = new BooleanQuery();//根据数字范围查询//查询文件大小,大于100 小于1000的文章//第一个参数:域名      第二个参数:最小值,  第三个参数:最大值, 第四个参数:是否包含最小值,   第五个参数:是否包含最大值Query numericQuery = NumericRangeQuery.newLongRange("fileSize", 100L, 1000L, true, true);//创建词元:就是词,   Term term = new Term("fileName", "apache");//使用TermQuery查询,根据term对象进行查询TermQuery termQuery = new TermQuery(term);//Occur是逻辑条件//must相当于and关键字,是并且的意思//should,相当于or关键字或者的意思//must_not相当于not关键字, 非的意思//注意:单独使用must_not  或者 独自使用must_not没有任何意义query.add(termQuery, Occur.MUST);query.add(numericQuery, Occur.MUST);//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(query, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}@Testpublic void testMathAllQuery() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();//查询所有文档MatchAllDocsQuery query = new MatchAllDocsQuery();//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(query, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}@Testpublic void testMultiFieldQueryParser() throws Exception{//创建分词器(创建索引和所有时所用的分词器必须一致)Analyzer analyzer = new IKAnalyzer();String [] fields = {"fileName","fileContext"};//从文件名称和文件内容中查询,只有含有apache的就查出来MultiFieldQueryParser multiQuery = new MultiFieldQueryParser(fields, analyzer);//输入需要搜索的关键字Query query = multiQuery.parse("apache");//指定索引和文档的目录Directory dir = FSDirectory.open(new File("E:\\dic"));//索引和文档的读取对象IndexReader indexReader = IndexReader.open(dir);//创建索引的搜索对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//搜索:第一个参数为查询语句对象, 第二个参数:指定显示多少条TopDocs topdocs = indexSearcher.search(query, 5);//一共搜索到多少条记录System.out.println("=====count=====" + topdocs.totalHits);//从搜索结果对象中获取结果集ScoreDoc[] scoreDocs = topdocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){//获取docIDint docID = scoreDoc.doc;//通过文档ID从硬盘中读取出对应的文档Document document = indexReader.document(docID);//get域名可以取出值 打印System.out.println("fileName:" + document.get("fileName"));System.out.println("fileSize:" + document.get("fileSize"));System.out.println("============================================================");}}}




1 0
原创粉丝点击