lucene入门体会
- 格式:doc
- 大小:208.50 KB
- 文档页数:31
lucene笔记-视频配套笔记传智播客 Java学院传智.入云龙全文检索技术之Lucene1 课程计划1、什么全文检索数据类型:结构化数据和非结构化数据非结构化数据查询方法全文检索的概念2、什么是Lucene3、Lucene实现全文检索的流程(重点)4、Lucene的入门程序(重点)5、分析器Analyzer(重点)7、索引库的维护(重点)i. 索引库的增加索引ii. 删除索引iii. 修改索引8、索引库的查询(重点)i. 使用Query的子类查询ii. 使用QueryParser查询8、相关的排序2 什么全文检索结构化数据:数据的长度类型是固定的。
数据库中的数据非结构化数据:长度不固定格式不固定。
Word文档、excel、pdf、txt。
2.1 结构化数据的查询使用sql语句查询就可以2.2 非结构化数据的查询需求:在文件中找出包含java字符的文档。
传智播客 Java学院传智.入云龙2.2.1 实现方法1、目测2、顺序扫描。
如果文件量大的话比如说20G,顺序扫描会变的很慢。
3、非结构化的数据变结构化先从文件中找出文件所有的词汇,形成一个列表。
查询的时候直接查询列表,找到关键词后根据这词找到相应的文档。
一次创建多次使用。
2.3 全文检索的概念这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。
2.4 全文检索应用领域1、搜索引擎,百度、谷歌2、站内搜索a) 微博搜索b) 论坛搜索3、电商搜索,搜索的是商品信息。
3 什么是Lucene3.1 Lucene的概念Lucene是apache下的一个开放源代码的全文检索引擎工具包。
提供了完整的查询引擎和索引引擎,部分文本分析引擎。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
3.2 Lucene和搜索引擎的区别Lucene是一个工具包:需要进行编程才能实现全文检索的功能呢搜索引擎:一套独立运行的系统,提供了全文检索功能。
lucene原理Lucene是Apache软件基金会下的一个开放源代码的全文信息检索的开发工具包,它实现了完整的文档搜索引擎。
它提供两种索引类型:结构化索引和文档索引,两种索引类型都有它们各自的优势和缺点,取决于实际需要。
Lucene提供了一个组件化的架构,它利用一个高效的索引系统来实现搜索。
此外,Lucene还提供了许多的文本处理功能,如词法分析,摘要,跟踪搜索日志,等等。
而且,Lucene和其他全文搜索系统不同,它允许用户定制自己的索引和结构,从而满足特定的搜索需求。
Lucene的核心是索引机制,它可以对一系列文档进行检索、搜索、高级搜索。
它利用微机二进制索引结构可以快速访问准确的结果,还可以在全文检索时进行模糊处理,识别文档中的同义词等。
Lucene还跟踪文档更新,可以检测何时需要重组全文索引,从而实现快速响应搜索需要。
除此之外,Lucene还可以搜索特定的文档,文本,页面,网页或者指定的网站。
Lucene的设计出发点是提供全文搜索的性能,而不仅仅是提供精确的搜索词语。
这意味着Lucene可以提供精确的搜索,使用的是数据结构和算法来实现搜索,搜索的结果可以按照权重排序,并且可以对搜索结果进行筛选,从而更好地满足搜索用户的需求。
Lucene通过提供文档过滤器和搜索过滤器,可以用来限定搜索结果的范围。
此外,Lucene 还提供了一系列的分析器,来处理原始的文档,包括不同类型的文件,如Word文档,PDF文档,HTML文档等等。
基于Lucene的搜索服务可以满足各种不同的搜索需求。
用户可以根据自己的关键字设置搜索条件,也可以应用不同类型的条件,如限制搜索结果的数量,搜索结果的排序等。
Lucene利用高效的计算方法和索引技术,能够提供快速准确的搜索结果,并对不同类型的数据进行处理,进一步提高搜索效率。
1Lucene学习资料大纲:了解搜索引擎基础知识Lucene快速入门常用查询技术亮点:搜索引擎面试问题:索引为什么能提高搜索效率lucene中的倒序索引与数据库索引的区别1.1搜索引擎基础知识1.1.1什么是索引[index] 是根据一定需要,把书刊中的主要内容或各种题名摘录下来,标明出处、页码,按一定次序分条排列,以供人查阅的资料。
索引是一本科技书籍的重要组成部分,它把书中的重要名词罗列出来,并给出它们相应的页码,方便读者快速查找该名词的定义和含义。
1.1.2数据库语义在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。
当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。
但是,考虑一下如下情形,按照商品名称(Title)来进行搜索,这时,用户输入的不可能是商品的完整名称,而只能是名称之中的一个词:面试小问题:使用like查询是否能使用索引?提示,mysql 中可以使用explain查看sql语句的执行计划这时如果按照传统索引技术,索引整个Title字段,仍然不能达到快速搜索的效果1.1.3倒排索引倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。
它是文档检索系统中最常用的数据结构。
通过倒排索引,可以根据单词快速获取包含这个单词的文档列表1.1.4全文检索的一般过程包括了数据收集(Gather Data)、建立索引、从索引中搜索这些部分1.1.5Gather Data输入的来源可能有:1)文件系统2)数据库3)网页4)人工输入1.1.6创建索引步骤:1)分词:将文档分成一一个单词去除标点符号去除停用词(Stop word)经过语言处理组件进行处理例如对于英语变为小写将单词缩减或转变为词根,例如复数=>单数过去式=>原型注意:lucene的默认分词并没有上述实现2)中文分词:分词算法可分为三大类:基于字典、词库匹配的分词方法;基于词频度统计的分词方法和基于知识理解的分词方法。
一、lucene模糊匹配原理概述lucene是一个开源的全文检索引擎工具,提供了强大的文本搜索和分析功能。
在实际应用中,经常需要进行模糊匹配,以处理用户输入的错别字、拼写错误或者同义词。
模糊匹配是lucene中非常重要的功能,它可以帮助用户找到相关的文档,提高搜索的准确性和全面性。
二、lucene模糊匹配的算法原理1. Levenshtein Distance算法Levenshtein Distance是衡量两个字符串相似程度的一种算法,也称为编辑距离。
在lucene中,模糊匹配主要使用Levenshtein Distance算法来实现。
该算法通过计算两个字符串之间的距离,从而确定它们的相似程度。
具体来说,它通过插入、删除和替换操作,将一个字符串转换成另一个字符串所需的最小步骤数来衡量相似度。
2. 模糊查询的实现方式在lucene中,模糊查询可以通过FuzzyQuery类来实现。
利用FuzzyQuery,可以指定一个最大编辑距离,从而允许匹配到具有一定相似度的文档。
FuzzyQuery会基于Levenshtein Distance算法来进行模糊匹配,找到编辑距离小于等于指定值的文档。
三、模糊匹配的应用场景1. 处理用户输入错误当用户在搜索框中输入错别字或者拼写错误时,模糊匹配可以帮助系统找到相关的文档,并提供纠正建议,提高搜索的准确性和用户体验。
2. 同义词匹配在自然语言处理中,同一个概念可能有多种不同的表达方式。
通过模糊匹配,可以将具有相似含义的词语进行匹配,从而提高搜索的全面性。
3. 解决词形变化问题词形变化是自然语言中常见的现象,同一个词可能有不同的变形形式。
通过模糊匹配,可以将不同词形的单词对应起来,使得搜索更加全面和准确。
四、模糊匹配的优化策略1. 设置合适的编辑距离阈值在使用模糊匹配时,需要根据具体的应用场景来设置合适的编辑距离阈值。
如果编辑距离过小,可能会产生大量的不必要匹配;如果编辑距离过大,可能会包含过多的无关文档。
es的lucene作用Es的Lucene作用Lucene是一个开源的全文搜索引擎库,被广泛应用于各种编程语言和领域,其中包括Elasticsearch(简称Es),是一个基于Lucene 构建的分布式搜索与分析引擎。
本文将重点介绍Es的Lucene作用,并探讨其在搜索引擎领域中的重要性。
一、Lucene的基本概念和原理Lucene是一个高效、可扩展的全文搜索引擎库,它提供了一套简单而强大的API,可以用于创建索引、搜索和生成文本摘要。
其核心原理是将文本数据分析、索引和搜索的过程进行分离,以实现高效的全文搜索。
1. 数据分析(Analysis):Lucene提供了一系列的文本分析器(Analyzer),用于将输入的文本进行分词、词干提取、大小写转换等处理。
分析器的作用是将原始文本转化为一组有意义的词条(Term),以便于后续的索引和搜索操作。
2. 索引(Indexing):Lucene使用倒排索引(Inverted Index)的方式来存储和管理文本数据。
倒排索引是一种将词条映射到文档的数据结构,它可以快速地根据词条进行搜索,并找到包含该词条的文档。
3. 搜索(Searching):Lucene提供了丰富的搜索API,可以根据关键词、短语、通配符等进行检索,并按照相关度对搜索结果进行排序。
搜索过程利用倒排索引来定位匹配的文档,并根据各种算法计算文档与查询的相关度。
二、Es中的Lucene应用Es是一个基于Lucene的分布式搜索与分析引擎,它在Lucene的基础上进行了功能扩展和性能优化,提供了更强大的分布式搜索和数据分析能力。
1. 分布式搜索:Es将数据分片存储在多个节点上,并使用分布式索引的方式来实现高性能的搜索。
当用户发起搜索请求时,Es会将查询分发到各个节点,并将结果进行合并和排序,最后返回给用户。
2. 数据分析与聚合:Es提供了丰富的数据聚合功能,可以对文档进行分组、统计、排序等操作。
用户可以通过聚合操作获取关于数据的各种统计信息,如平均值、最大值、最小值等,以及根据条件进行数据筛选和分析。
lucene算法原理Lucene算法原理Lucene是一个开源的全文检索引擎工具包,采用Java语言编写,被广泛应用于各类信息检索系统中。
它的核心思想是将文本信息转化为可被计算机理解和处理的数据结构,以实现高效的文本搜索和检索功能。
本文将介绍Lucene算法的原理及其核心组成部分。
一、倒排索引Lucene的核心数据结构是倒排索引(Inverted Index),它是一种将文档中的单词映射到文档的数据结构。
传统的索引方式是顺序索引,即根据文档顺序逐个记录单词。
而倒排索引则是根据单词逐个记录文档,将每个单词对应的文档存储在一个倒排列表中。
这种方式可以极大地提高搜索效率,因为它能够快速地找到包含某个特定单词的文档。
二、分词器在构建倒排索引前,需要将文本进行分词处理。
分词器(Tokenizer)将文本切分成一个个独立的词项(Term),并去除停用词等无关信息。
Lucene提供了多种分词器,如标准分词器(StandardTokenizer)、简单分词器(SimpleTokenizer)等,用户也可以自定义分词器以适应不同的需求。
三、索引构建索引构建是指将文档转化为倒排索引的过程。
首先,需要创建一个索引目录(Index Directory),用于存储索引文件;然后,通过Analyzer对文档进行分词处理;最后,将分词结果按照倒排索引的结构存储到索引目录中。
四、搜索过程Lucene的搜索过程主要包括查询解析、查询扩展和评分排序三个步骤。
1. 查询解析:用户输入的查询语句经过查询解析器(Query Parser)处理,将其解析为一个个查询表达式。
查询解析器支持多种查询语法,如布尔查询、模糊查询、范围查询等。
2. 查询扩展:为了提高搜索的准确性和覆盖率,Lucene支持查询扩展功能。
通过分析用户查询的上下文,自动为查询语句添加相关的词项,从而扩展查询范围。
3. 评分排序:Lucene使用TF-IDF算法对搜索结果进行评分排序。
一步一步跟我学习lucene(8)---lucene搜索之索引的查询原理和查询工具类昨天我们了解了lucene搜索之IndexSearcher构建过程(/wuyinggui10000/article/details/4569866 7),对lucene的IndexSearcher有一个大体的了解,知道了怎么创建IndexSearcher,就要开始学会使用IndexSearcher进行索引的搜索,本节我们学习索引的查询原理和根据其相关原理写索引查询的工具类的编写;IndexSearcher常用方法IndexSearcher提供了几个常用的方法:•IndexSearcher.doc(int docID) 获取索引文件中的第n个索引存储的相关字段,返回为Document类型,可以据此读取document 中的Field.STORE.YES的字段;•IndexSearcher.doc(int docID, StoredFieldVisitor fieldVisitor) 获取StoredFieldVisitor指定的字段的document,StoredFieldVisitor定义如下[java] view plain copy1.StoredFieldVisitor visitor = new DocumentStoredFieldVisi tor(String... fields);•IndexSearcher.doc(int docID, Set<String> fieldsToLoad) 此方法同上边的IndexSearcher.doc(int docID, StoredFieldVisitor fieldVisitor) ,其实现如下图•IndexSearcher.count(Query query) 统计符合query条件的document个数•IndexSearcher.searchAfter(final ScoreDoc after, Queryquery, int numHits) 此方法会返回符合query查询条件的且在after 之后的numHits条记录;其实现原理为:先读取当前索引文件的最大数据条数limit,然后判断after是否为空和after对应的document的下标是否超出limit的限制,如果超出的话抛出非法的参数异常;设置读取的条数为numHits和limit中最小的(因为有超出最大条数的可能,避免超出限制而造成的异常)接下来创建一个CollectorManager类型的对象,该对象定义了要返回的T opDocs的个数,上一页的document的结尾(after),并且对查询结果进行分析合并最后调用search(query,manager)来查询结果•IndexSearcher.search(Query query, int n) 查询符合query条件的前n个记录•IndexSearcher.search(Query query, Collector results) 查询符合collector的记录,collector定义了分页等信息•IndexSearcher.search(Query query, int n,Sort sort, boolean doDocScores, boolean doMaxScore) 实现任意排序的查询,同时控制是否计算hit score和max score是否被计算在内,查询前n条符合query条件的document;•IndexSearcher.search(Query query, CollectorManager<C, T>collectorManager) 利用给定的collectorManager获取符合query 条件的结果,其执行流程如下:先判断是否有ExecutorService执行查询的任务,如果没有executor,IndexSearcher会在单个任务下进行查询操作;如果IndexSearcher有executor,则会由每个线程控制一部分索引的读取,而且查询的过程中采用的是future机制,此种方式是边读边往结果集里边追加数据,这种异步的处理机制也提升了效率,其执行过程如下:编码实践我中午的时候写了一个SearchUtil的工具类,里边添加了多目录查询和分页查询的功能,经测试可用,工具类和测试的代码如下:[java] view plain copy1.package com.lucene.search.util;2.3.import java.io.File;4.import java.io.IOException;5.import java.nio.file.Paths;6.import java.util.Set;7.import java.util.concurrent.ExecutorService;8.9.import org.apache.lucene.document.Document;10.import org.apache.lucene.index.DirectoryReader;11.import org.apache.lucene.index.IndexReader;12.import org.apache.lucene.index.MultiReader;13.import org.apache.lucene.search.BooleanQuery;14.import org.apache.lucene.search.IndexSearcher;15.import org.apache.lucene.search.Query;16.import org.apache.lucene.search.ScoreDoc;17.import org.apache.lucene.search.TopDocs;18.import org.apache.lucene.search.BooleanClause.Occur ;19.import org.apache.lucene.store.FSDirectory;20.21./**lucene索引查询工具类22.* @author lenovo23.*24.*/25.public class SearchUtil {26./**获取IndexSearcher对象27.* @param indexPath28.* @param service29.* @return30.* @throws IOException31.*/32.public static IndexSearcher getIndexSearcherByParent Path(String parentPath,ExecutorService service) throws IOExcep tion{33.MultiReader reader = null;34.//设置35.try {36.File[] files = new File(parentPath).listFiles();37.IndexReader[] readers = new IndexReader[files.length] ;38.for (int i = 0 ; i < files.length ; i ++) {39.readers[i] = DirectoryReader.open(FSDirectory.open(P aths.get(files[i].getPath(), new String[0])));40.}41.reader = new MultiReader(readers);42.} catch (IOException e) {43.// TODO Auto-generated catch block44. e.printStackTrace();45.}46.return new IndexSearcher(reader,service);47.}48./**根据索引路径获取IndexReader49.* @param indexPath50.* @return51.* @throws IOException52.*/53.public static DirectoryReader getIndexReader(String i ndexPath) throws IOException{54.return DirectoryReader.open(FSDirectory.open(Paths.g et(indexPath, new String[0])));55.}56./**根据索引路径获取IndexSearcher57.* @param indexPath58.* @param service59.* @return60.* @throws IOException61.*/62.public static IndexSearcher getIndexSearcherByIndex Path(String indexPath,ExecutorService service) throws IOExcepti on{63.IndexReader reader = getIndexReader(indexPath);64.return new IndexSearcher(reader,service);65.}66.67./**如果索引目录会有变更用此方法获取新的IndexSearcher这种方式会占用较少的资源68.* @param oldSearcher69.* @param service70.* @return71.* @throws IOException72.*/73.public static IndexSearcher getIndexSearcherOpenIfC hanged(IndexSearcher oldSearcher,ExecutorService service) thr ows IOException{74.DirectoryReader reader = (DirectoryReader) oldSearch er.getIndexReader();75.DirectoryReader newReader = DirectoryReader.openIf Changed(reader);76.return new IndexSearcher(newReader, service);77.}78.79./**多条件查询类似于sql in80.* @param querys81.* @return82.*/83.public static Query getMultiQueryLikeSqlIn(Query ...querys){84.BooleanQuery query = new BooleanQuery();85.for (Query subQuery : querys) {86.query.add(subQuery,Occur.SHOULD);87.}88.return query;89.}90.91./**多条件查询类似于sql and92.* @param querys93.* @return94.*/95.public static Query getMultiQueryLikeSqlAnd(Query .. . querys){96.BooleanQuery query = new BooleanQuery();97.for (Query subQuery : querys) {98.query.add(subQuery,Occur.MUST);99.}100.return query;101.}102./**根据IndexSearcher和docID获取默认的document 103.* @param searcher104.* @param docID105.* @return106.* @throws IOException107.*/108.public static Document getDefaultFullDocument(Inde xSearcher searcher,int docID) throws IOException{109.return searcher.doc(docID);110.}111./**根据IndexSearcher和docID112.* @param searcher113.* @param docID114.* @param listField115.* @return116.* @throws IOException117.*/118.public static Document getDocumentByListField(Inde xSearcher searcher,int docID,Set<String> listField) throws IOExc eption{119.return searcher.doc(docID, listField);120.}121.122./**分页查询123.* @param page 当前页数124.* @param perPage 每页显示条数125.* @param searcher searcher查询器126.* @param query 查询条件127.* @return128.* @throws IOException129.*/130.public static TopDocs getScoreDocsByPerPage(int pa ge,int perPage,IndexSearcher searcher,Query query) throws IOE xception{131.TopDocs result = null;132.if(query == null){133.System.out.println(" Query is null return null ");134.return null;135.}136.ScoreDoc before = null;137.if(page != 1){138.TopDocs docsBefore = searcher.search(query, (page-1)*perPage);139.ScoreDoc[] scoreDocs = docsBefore.scoreDocs;140.if(scoreDocs.length > 0){141.before = scoreDocs[scoreDocs.length - 1];142.}143.}144.result = searcher.searchAfter(before, query, perPage);145.return result;146.}147.public static TopDocs getScoreDocs(IndexSearcher se archer,Query query) throws IOException{148.TopDocs docs = searcher.search(query, getMaxDocId(s earcher));149.return docs;150.}151./**统计document的数量,此方法等同于matchAllDocsQuery查询152.* @param searcher153.* @return154.*/155.public static int getMaxDocId(IndexSearcher searcher ){156.return searcher.getIndexReader().maxDoc();157.}158.159.}相关测试代码如下:[java] view plain copy1.package com.lucene.index.test;2.3.import java.io.IOException;4.import java.util.HashSet;5.import java.util.Set;6.import java.util.concurrent.ExecutorService;7.import java.util.concurrent.Executors;8.9.import org.apache.lucene.document.Document;10.import org.apache.lucene.index.Term;11.import org.apache.lucene.search.IndexSearcher;12.import org.apache.lucene.search.Query;13.import org.apache.lucene.search.ScoreDoc;14.import org.apache.lucene.search.TermQuery;15.import org.apache.lucene.search.TopDocs;16.17.import com.lucene.search.util.SearchUtil;18.19.public class TestSearch {20.public static void main(String[] args) {21.ExecutorService service = Executors.newCachedThrea dPool();22.try {23.24.IndexSearcher searcher = SearchUtil.getIndexSearcher ByParentPath("index",service);25.System.out.println(SearchUtil.getMaxDocId(searcher));26.Term term = new Term("content", "lucene");27.Query query = new TermQuery(term);28.TopDocs docs = SearchUtil.getScoreDocsByPerPage(2, 20, searcher, query);29.ScoreDoc[] scoreDocs = docs.scoreDocs;30.System.out.println("所有的数据总数为:"+docs.totalHits);31.System.out.println("本页查询到的总数为:"+scoreDocs.length);32.for (ScoreDoc scoreDoc : scoreDocs) {33.Document doc = SearchUtil.getDefaultFullDocument(s earcher, scoreDoc.doc);34.//System.out.println(doc);35.}36.System.out.println("\n\n");37.TopDocs docsAll = SearchUtil.getScoreDocs(searcher, query);38.Set<String> fieldSet = new HashSet<String>();39.fieldSet.add("path");40.fieldSet.add("modified");41.for (int i = 0 ; i < 20 ; i ++) {42.Document doc = SearchUtil.getDocumentByListField(s earcher, docsAll.scoreDocs[i].doc,fieldSet);43.System.out.println(doc);44.}45.46.} catch (IOException e) {47.// TODO Auto-generated catch block48. e.printStackTrace();49.}finally{50.service.shutdownNow();51.}52.}53.54.}。
2012/2/26一、摘要本文档是在完成山东农信知识库项目的基础上编写的,简要介绍了lucene技术的原理、分词技术、索引技术、文档权重、文档排重技术等,本文档的定位是lucene初级开发人员,如果您已经是lucene专家或者是搜索引擎的大牛,就没必要来看本文档了。
本文档的所有编码是基于lucene 3.0.4完成的,使用的是标准分析器,对于不同的lucene版本或者不同的分析器,代码会有一定的差异。
二、Lucene全文检索的实现Lucene是一个高效的全文检索库。
相信各位同事在项目中通过数据库检索的案例很多,数据库检索大家一定非常熟悉了,我们知道在正常情况下数据库查询搜索能够满足我们的需求,那为什么还要用到lucene全文检索呢?在学习lucene之前,我们先了解一下全文检索吧。
数据分为两种:结构化数据和全文数据(又叫做非结构化数据)。
•结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
•全文数据:指不定长或无固定格式的数据,如邮件,word文档等。
对结构化数据的搜索,我们一般用到数据库比较多。
那对于全文数据的搜索呢?我们需要针对全文数据制定全文搜索的方式,其中像lucene这样,先建立索引,再对索引进行搜索就是其中的一种。
Lucene是一个基于java的全文索引引擎工具包,它提供了各种借口,可以方便的此文档讲述了lucent技术的基本用法,包括分词、索引、排重等技术。
嵌入到各种应用中,通过对接口的实现满足我们全文索引或者检索功能。
在对非结构化数据索引之前,我们需要先将数据进行分词处理,对于英文分词比较简单,一个空格间隔就是一个单词,而对于中文,我们如何将中文的词提取出来再进行索引难度就比较大了。
Lucene提供了多种语言分析器,在本文档的第四节中,我们将会对lucene分词技术做详细的讲解。
在对文字进行关键字提取之后,下一步就需要对内容进行索引了。
索引是通过document存储的,document可以设定多个field字段,根据需要按照规则索引或者存储字段。
一步一步跟我学习lucene(14)---lucene搜索之facet查询原理和facet查询实例Facet说明我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为例,我们选择某一个品牌,系统会将该品牌对应的商品展示出来,效果图如下:如上图,我们关注的是品牌,选购热点等方面,对于类似的功能我们用lucene的term查询当然可以,但是在数据量特别大的情况下还用普通查询来实现显然会因为FSDirectory.open等耗时的操作造成查询效率的低下,同时普通查询是全部document都扫描一遍,这样显然造成了查询效率低;lucene提供了facet查询用于对同一类的document进行聚类化,这样在查询的时候先关注某一个方面,这种显然缩小了查询范围,进而提升了查询效率;facet模块提供了多个用于处理facet的统计和值处理的方法;要实现facet的功能,我们需要了解facetField,FacetField定义了dim和此field对应的path,需要特别注意的是我们在做facetField索引的时候,需要事先调用FacetsConfig.build(Document);FacetField的indexOptions设置为了DOCS_AND_FREQS_AND_POSITIONS的,即既索引又统计出现的频次和出现的位置,这样做主要是为了方便查询和统计;相应的在存储的时候我们需要利用FacetsConfig和DirectoryTaxonomyWriter;DirectoryTaxonomyWriter用来利用Directory来存储T axono 信息到硬盘;DirectoryTaxonomyWriter的构造器如下:[java] view plain copy1.public DirectoryTaxonomyWriter(Directory directory, Ope nMode openMode,2.TaxonomyWriterCache cache) throws IOException {3.4.dir = directory;5.IndexWriterConfig config = createIndexWriterConfig(ope nMode);6.indexWriter = openIndexWriter(dir, config);7.8.// verify (to some extent) that merge policy in effect would preserve category docids9.assert !(indexWriter.getConfig().getMergePolicy() instanc eof TieredMergePolicy) :10."for preserving category docids, merging none-adjacent segments is not allowed";11.12.// after we opened the writer, and the index is locked, it's safe to check13.// the commit data and read the index epoch14.openMode = config.getOpenMode();15.if (!DirectoryReader.indexExists(directory)) {16.indexEpoch = 1;17.} else {18.String epochStr = null;19.Map<String, String> commitData = readCommitData( directory);20.if (commitData != null) {21.epochStr = commitData.get(INDEX_EPOCH);22.}23.// no commit data, or no epoch in it means an old tax onomy, so set its epoch to 1, for lack24.// of a better value.25.indexEpoch = epochStr == null ? 1 : Long.parseLong( epochStr, 16);26.}27.28.if (openMode == OpenMode.CREATE) {29.++indexEpoch;30.}31.32.FieldType ft = new FieldType(TextField.TYPE_NOT_STO RED);33.ft.setOmitNorms(true);34.parentStreamField = new Field(Consts.FIELD_PAYLOAD S, parentStream, ft);35.fullPathField = new StringField(Consts.FULL, "", Field.S tore.YES);36.37.nextID = indexWriter.maxDoc();38.39.if (cache == null) {40.cache = defaultTaxonomyWriterCache();41.}42.this.cache = cache;43.44.if (nextID == 0) {45.cacheIsComplete = true;46.// Make sure that the taxonomy always contain the ro ot category47.// with category id 0.48.addCategory(new FacetLabel());49.} else {50.// There are some categories on the disk, which we ha ve not yet51.// read into the cache, and therefore the cache is inco mplete.52.// We choose not to read all the categories into the ca che now,53.// to avoid terrible performance when a taxonomy ind ex is opened54.// to add just a single category. We will do it later, afte r we55.// notice a few cache misses.56.cacheIsComplete = false;57.}58.}由上述代码可知,DirectoryTaxonomyWriter先打开一个IndexWriter,在确保indexWriter打开和locked的前提下,读取directory对应的segments中需要提交的内容,如果读取到的内容为空,说明是上次的内容,设置indexEpoch为1,接着对cache进行设置;判断directory中是否还包含有document,如果有设置cacheIsComplete为false,反之为true;时候不早了,今天先写到这里,明天会在此基础上补充,大家见谅编程实践我对之前的读取文件夹内容的做了个facet索引的例子对BaseIndex修改了facet的设置,相关代码如下[java] view plain copy1.package com.lucene.index;2.3.4.5.import java.io.File;6.import java.io.IOException;7.import java.nio.file.Paths;8.import java.text.ParseException;9.import java.util.List;10.import java.util.concurrent.CountDownLatch;11.12.import org.apache.lucene.document.Document;13.import org.apache.lucene.document.Field;14.import org.apache.lucene.facet.FacetResult;15.import org.apache.lucene.facet.Facets;16.import org.apache.lucene.facet.FacetsCollector;17.import org.apache.lucene.facet.FacetsConfig;18.import org.apache.lucene.facet.taxonomy.FastTaxono myFacetCounts;19.import org.apache.lucene.facet.taxonomy.directory.Dir ectoryTaxonomyReader;20.import org.apache.lucene.facet.taxonomy.directory.Dir ectoryTaxonomyWriter;21.import org.apache.lucene.index.IndexOptions;22.import org.apache.lucene.index.IndexWriter;23.import org.apache.lucene.index.Term;24.import org.apache.lucene.search.IndexSearcher;25.import org.apache.lucene.search.MatchAllDocsQuery;26.import org.apache.lucene.search.Query;27.import org.apache.lucene.store.Directory;28.import org.apache.lucene.store.FSDirectory;29.import org.apache.lucene.store.RAMDirectory;30.31.import com.lucene.search.SearchUtil;32.33.34.public abstract class BaseIndex<T> implements Run nable{35./**36.* 父级索引路径37.*/38.private String parentIndexPath;39./**40.* 索引编写器41.*/42.private IndexWriter writer;43.private int subIndex;44./**45.* 主线程46.*/47.private final CountDownLatch countDownLatch1;48./**49.*工作线程50.*/51.private final CountDownLatch countDownLatch2;52./**53.* 对象列表54.*/55.private List<T> list;56./**57.* facet查询58.*/59.private String facet;60.protected final FacetsConfig config = new FacetsConf ig();61.protected final static String indexPath = "index1";62.protected final static DirectoryTaxonomyWriter taxo Writer;63.static{64.try {65.Directory directory = FSDirectory.open(Paths.get(inde xPath, new String[0]));66.taxoWriter = new DirectoryTaxonomyWriter(directory) ;67.} catch (IOException e) {68.throw new ExceptionInInitializerError("BaseIndex initi alizing error");69.}70.}71.public BaseIndex(IndexWriter writer,CountDownLatch countDownLatch1, CountDownLatch countDownLatch2,72.List<T> list, String facet){73.super();74.this.writer = writer;75.this.countDownLatch1 = countDownLatch1;76.this.countDownLatch2 = countDownLatch2;77.this.list = list;78.this.facet = facet;79.}80.public BaseIndex(String parentIndexPath, int subIndex ,81.CountDownLatch countDownLatch1, CountDownLatch countDownLatch2,82.List<T> list) {83.super();84.this.parentIndexPath = parentIndexPath;85.this.subIndex = subIndex;86.try {87.//多目录索引创建88.File file = new File(parentIndexPath+"/index"+subInd ex);89.if(!file.exists()){90.file.mkdir();91.}92.this.writer = IndexUtil.getIndexWriter(parentIndexPath +"/index"+subIndex, true);93.} catch (IOException e) {94.// TODO Auto-generated catch block95. e.printStackTrace();96.};97.this.subIndex = subIndex;98.this.countDownLatch1 = countDownLatch1;99.this.countDownLatch2 = countDownLatch2;100.this.list = list;101.}102.public BaseIndex(String path,CountDownLatch count DownLatch1, CountDownLatch countDownLatch2,103.List<T> list) {104.super();105.try {106.//单目录索引创建107.File file = new File(path);108.if(!file.exists()){109.file.mkdir();110.}111.this.writer = IndexUtil.getIndexWriter(path,true);112.} catch (IOException e) {113.// TODO Auto-generated catch block114. e.printStackTrace();115.};116.this.countDownLatch1 = countDownLatch1;117.this.countDownLatch2 = countDownLatch2;118.this.list = list;119.}120.121./**创建索引122.* @param writer123.* @param carSource124.* @param create125.* @throws IOException126.* @throws ParseException127.*/128.public abstract void indexDoc(IndexWriter writer,T t) throws Exception;129./**批量索引创建130.* @param writer131.* @param t132.* @throws Exception133.*/134.public void indexDocs(IndexWriter writer,List<T> t) th rows Exception{135.for (T t2 : t) {136.indexDoc(writer,t2);137.}138.}139./**带group的索引创建140.* @param writer141.* @param docs142.* @throws IOException143.*/144.public void indexDocsWithGroup(IndexWriter writer,S tring groupFieldName,String groupFieldValue,List<Document> docs) throws IOException{145.Field groupEndField = new Field(groupFieldName, gro upFieldValue, Field.Store.NO, Field.Index.NOT_ANALYZED);146.docs.get(docs.size()-1).add(groupEndField);147.//148.writer.updateDocuments(new Term(groupFieldName, groupFieldValue),docs);mit();150.writer.close();151.}152.@Override153.public void run() {154.try {155.countDownLatch1.await();156.System.out.println(writer);157.indexDocs(writer,list);158.} catch (InterruptedException e) {159.// TODO Auto-generated catch block160. e.printStackTrace();161.} catch (Exception e) {162.// TODO Auto-generated catch block163. e.printStackTrace();164.}finally{165.countDownLatch2.countDown();166.try {mit();168.writer.close();169.} catch (IOException e) {170.// TODO Auto-generated catch block171. e.printStackTrace();172.}173.}174.}175.}相应得,document的索引需要利用DirectoryTaxonomyWriter 来进行原有document的处理[java] view plain copy1.package com.lucene.index;2.3.import java.util.List;4.import java.util.concurrent.CountDownLatch;5.6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.LongField;9.import org.apache.lucene.document.StringField;10.import org.apache.lucene.document.TextField;11.import org.apache.lucene.facet.FacetField;12.import org.apache.lucene.index.IndexWriter;13.import org.apache.lucene.index.IndexWriterConfig;14.import org.apache.lucene.index.Term;15.16.import com.lucene.bean.FileBean;17.18.public class FileBeanIndex extends BaseIndex<FileBe an>{19.private static String facet;20.21.public FileBeanIndex(IndexWriter writer, CountDownL atch countDownLatch12, CountDownLatch countDownLatch1,22.List<FileBean> fileBeans, String facet1) {23.super(writer, countDownLatch12, countDownLatch1, fi leBeans, facet);24.facet = facet1;25.}26.@Override27.public void indexDoc(IndexWriter writer, FileBean t) t hrows Exception {28.Document doc = new Document();29.String path = t.getPath();30.System.out.println(t.getPath());31.doc.add(new StringField("path", path, Field.Store.YES)) ;32.doc.add(new LongField("modified", t.getModified(), Fi eld.Store.YES));33.doc.add(new TextField("content", t.getContent(), Field. Store.YES));34.doc.add(new FacetField("filePath", new String[]{facet}) );35.//doc = config.build(taxoWriter,doc);36.if (writer.getConfig().getOpenMode() == IndexWriterC onfig.OpenMode.CREATE){37.//writer.addDocument(doc);38.writer.addDocument(this.config.build(taxoWriter, doc) );39.}else{40.writer.updateDocument(new Term("path", t.getPath()), this.config.build(taxoWriter, doc));41.}mit();43.}44.45.46.}测试facet功能的测试类:[java] view plain copy1.package com.lucene.search;2.3.import java.io.IOException;4.import java.nio.file.Paths;5.import java.util.ArrayList;6.import java.util.List;7.8.import org.apache.lucene.facet.FacetResult;9.import org.apache.lucene.facet.Facets;10.import org.apache.lucene.facet.FacetsCollector;11.import org.apache.lucene.facet.FacetsConfig;12.import belAndValue;13.import org.apache.lucene.facet.taxonomy.FastTaxono myFacetCounts;14.import org.apache.lucene.facet.taxonomy.TaxonomyR eader;15.import org.apache.lucene.facet.taxonomy.directory.Dir ectoryTaxonomyReader;16.import org.apache.lucene.index.DirectoryReader;17.import org.apache.lucene.search.IndexSearcher;18.import org.apache.lucene.search.MatchAllDocsQuery;19.import org.apache.lucene.search.Query;20.import org.apache.lucene.store.Directory;21.import org.apache.lucene.store.FSDirectory;22.import org.junit.Test;23.24.public class TestSearchFacet {25.public static Directory directory;26.public static Directory taxoDirectory;27.public static TaxonomyReader taxoReader;28.protected final static FacetsConfig config = new Face tsConfig();29.static {30.try {31.directory = FSDirectory.open(Paths.get("index", new S tring[0]));32.taxoDirectory = FSDirectory.open(Paths.get("index1", new String[0]));33.taxoReader = new DirectoryTaxonomyReader(taxoDire ctory);34.} catch (IOException e) {35.// TODO Auto-generated catch block36. e.printStackTrace();37.}38.}39.40.public static void testSearchFacet() {41.try {42.DirectoryReader indexReader = DirectoryReader.open( directory);43.IndexSearcher searcher = new IndexSearcher(indexRe ader);44.FacetsCollector fc = new FacetsCollector();45.FacetsCollector.search(searcher, new MatchAllDocsQu ery(), indexReader.maxDoc(), fc);46.Facets facets = new FastTaxonomyFacetCounts(taxoRe ader, config, fc);47.List<FacetResult> results =facets.getAllDims(100);48.for (FacetResult facetResult : results) {49.System.out.println(facetResult.dim);belAndValue[] values = belValues;51.for (LabelAndValue labelAndValue : values) {52.System.out.println("\t"+bel +" "+l abelAndValue.value);53.}54.55.}56.57.indexReader.close();58.taxoReader.close();59.} catch (IOException e) {60.// TODO Auto-generated catch block61. e.printStackTrace();62.}63.}64.65.public static void main(String[] args) {66.testSearchFacet();67.}68.69.}。
1.概述Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。
Lucene以其方便使用、快速实施以及灵活性受到广泛的关注。
它可以方便地嵌入到各种应用中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。
2.lucene 的包结构1、org.apache.lucene.analysis对需要建立索引的文本进行分词、过滤等操作, 语言分析器,主要用于的切词Analyzer是一个抽象类,管理对文本内容的切分词规则。
2、org.apache.lucene.analysis.standard是标准分析器3、org.apache.lucene.document提供对Document和Field的各种操作的支持。
索引存储时的文档结构管理,类似于关系型数据库的表结构。
Document相对于关系型数据库的记录对象,Field主要负责字段的管理。
4、org.apache.lucene.index是最重要的包,用于向Lucene提供建立索引时各种操作的支持。
索引管理,包括索引建立、删除等。
索引包是整个系统核心,全文检索的根本就是为每个切出来的词建索引,查询时就只需要遍历索引,而不需要去正文中遍历,从而极大的提高检索效率。
5、org.apache.lucene.queryParser提供检索时的分析支持。
查询分析器,实现查询关键词间的运算,如与、或、非等。
6、org.apache.lucene.search 负责检索。
检索管理,根据查询条件,检索得到结果。
7、org.apache.lucene.store提供对索引存储的支持。
数据存储管理,主要包括一些底层的I/0操作。
8、org.apache.lucene.util提供一些常用工具类和常量类的支持3.索引文件格式a).fnm格式包含了Document中所有field名称b).fdt与.fdx格式.fdt文件用于存储具有Store.YES属性的Field的数据;.fdx是一个索引,用于存储Document在.fdt中的位置。
申明:原文来自/98440293.html1 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品.因此它并不像 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品.1.2 lucene能做什么要回答这个问题,先要了解lucene地本质.实际上lucene地功能很单一,说到底,就是你给它若干个字符串,然后它为你提供一个全文搜索服务,告诉你你要搜索地关键词出现在哪里.知道了这个本质,你就可以发挥想象做任何符合这个条件地事情了.你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表地若干个字段索引起来,那就不用再担心因为“%like%”而锁表了;你也可以写个自己地搜索引擎……1.3 你该不该选择lucene下面给出一些测试数据,如果你觉得可以接受,那么可以选择.测试一:250万记录,300M左右文本,生成索引380M左右,800线程下平均处理时间300ms. 测试二:37000记录,索引数据库中地两个varchar字段,索引文件2.6M,800线程下平均处理时间1.5ms.2 lucene地工作方式lucene提供地服务实际包含两部分:一入一出.所谓入是写入,即将你提供地源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源.2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选).将源中需要地信息加入Document地各个Field中,并把需要索引地Field索引起来,把需要存储地Field存储起来.将索引写入存储器,存储器可以是内存或磁盘.2.2读出流程用户提供搜索关键词,经过analyzer处理.对处理后地关键词搜索索引找出对应地Document.用户根据需要从找到地Document中提取需要地Field.3 一些需要知道地概念lucene用到一些概念,了解它们地含义,有利于下面地讲解.3.1 analyzerAnalyzer 是分析器,它地作用是把一个字符串按某种规则划分成一个个词语,并去除其中地无效词语,这里说地无效词语是指英文中地“of”、“the”,中文中地“地”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率.分词地规则千变万化,但目地只有一个:按语义划分.这点在英文中比较容易实现,因为英文本身就是以单词为单位地,已经用空格分开;而中文则必须以某种方法将连成一片地句子划分成一个个词语.具体划分方法下面再详细介绍,这里只需了解分析器地概念即可.3.2 document 用户提供地源是一条条记录,它们可以是文本文件、字符串或者数据库表地一条记录等等.一条记录经过索引之后,就是以一个Document地形式存储在索引文件中地.用户进行搜索,也是以Document列表地形式返回.3.3 field一个Document可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过Field在Document中存储地.Field有两个属性可选:存储和索引.通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引.这看起来似乎有些废话,事实上对这两个属性地正确组合很重要,下面举例说明:还是以刚才地文章为例子,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为真,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域地存储属性设置为真,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域地存储属性设置为假,当需要时再直接读取文件;我们只是希望能从搜索解果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域地存储属性设置为真,索引属性设置为假.上面地三个域涵盖了两个属性地三种组合,还有一种全为假地没有用到,事实上Field不允许你那么设置,因为既不存储又不索引地域是没有意义地.3.4 termterm是搜索地最小单位,它表示文档地一个词语,term由两部分组成:它表示地词语和这个词语所出现地field.3.5 tockentocken是term地一次出现,它包含trem文本和相应地起止偏移,以及一个类型字符串.一句话中可以出现多次相同地词语,它们都用同一个term表示,但是用不同地tocken,每个tocken标记该词语出现地地方.3.6 segment添加索引时并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同地小文件,然后再合并成一个大索引文件,这里每个小文件都是一个segment.4 lucene地结构lucene包括core和sandbox两部分,其中core是lucene稳定地核心部分,sandbox包含了一些附加功能,例如highlighter、各种分析器.Lucene core有七个包:analysis,document,index,queryParser,search,store,util.4.1 analysis Analysis包含一些内建地分析器,例如按空白字符分词地WhitespaceAnalyzer,添加了stopwrod 过滤地StopAnalyzer,最常用地StandardAnalyzer.4.2 documentDocument包含文档地数据结构,例如Document类定义了存储文档地数据结构,Field类定义了Document地一个域.4.3 indexIndex 包含了索引地读写类,例如对索引文件地segment进行写、合并、优化地IndexWriter 类和对索引进行读取和删除操作地IndexReader类,这里要注意地是不要被IndexReader这个名字误导,以为它是索引文件地读取类,实际上删除索引也是由它完成, IndexWriter只关心如何将索引写入一个个segment,并将它们合并优化;IndexReader则关注索引文件中各个文档地组织形式.4.4 queryParserQueryParser 包含了解读查询语句地类,lucene地查询语句和sql语句有点类似,有各种保留字,按照一定地语法可以组成各种查询. Lucene有很多种Query类,它们都继承自Query,执行各种特殊地查询,QueryParser地作用就是解读查询语句,按顺序调用各种Query类查找出结果.4.5 searchSearch包含了从索引中搜索结果地各种类,例如刚才说地各种Query类,包括TermQuery、BooleanQuery等就在这个包里.4.6 storeStore包含了索引地存储类,例如Directory定义了索引文件地存储结构,FSDirectory为存储在文件中地索引,RAMDirectory为存储在内存中地索引,MmapDirectory为使用内存映射地索引.4.7 utilUtil包含一些公共工具类,例如时间和字符串之间地转换工具.5 如何建索引5.1 最简单地能完成索引地代码片断IndexWrite r writer = new IndexWriter(“/data/index/”, new StandardAnalyzer(), true)。
lucene语法Lucene语法简介Lucene语法是一种支持高效索引和搜索文档的语言。
它使用定义域和查询语句来检索信息。
Lucene语法从两个不同的方面给用户提供支持:通过埙伊定义域可以定义检索信息的格式和结构;通过查询语句,可以检索匹配查询命令的索引数据。
Lucene容许对文档按字段进行搜索,可以同时让若干字段满足一定的要求,使用Lucene能加快索索引,检索结果的准确度有保障,只是在使用的时候需要合理的选择Lucene的查询功能,合理应用Lucene 语法,才能获得最大的效率和最佳的搜索准确性。
Lucene语法的结构Lucene语法的结构主要由域字段、查询对象和查询运算符组成。
域字段是定义信息格式和结构的一个字段,查询对象是指搜索文档或数据库中的一项或多项信息,查询语句中必不可少的内容;最后便是查询运算符,它有模糊查询、前缀查询、正则表达式查询,并且支持真/假查询和短暂的“数据文本和语句”等多种查询操作。
Lucene语法的基本操作1. 加载Lucene索引,创建索引路径。
2. 载入域字段:添加要被索引或查询的域字段,以及每个域字段的定义格式,定义字段中每个字段的类型,以及每个字段的查询方式等。
3. 提供查询条件:你可以提供多项查询条件,比如查询关键词、短语和某个字段的组合等等。
4. 调用索引查询,按查询语句检索索引数据,可以为每个查询规则设定权重值,可以根据要求改变搜索结果中每个文档的排序。
5. 加载查询结果:可以在窗口中显示查询结果,结果可以控制格式,按字段格式排版,支持结果表格和文本、HTML等格式的输出。
总结Lucene语法是一种支持高效索引和搜索文档的语言,结构由域字段、查询对象和操作符组成。
它不仅有利于索索引的快速,而且有助于提高查询准确率,只要正确地使用Lucene语法,就能够获得最佳的效果。
lucene学习1. 基本概念信息检索(IR)是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。
文档:用于搜索的内容部件。
文档过滤器:将文本格式信息从原始内容中提取出来,便于后期建立搜索引擎文档。
如Tika,与数据库的内容连接,DBSight、Hibernate Search、LuSQL、Compass和Oracle/Lucene集成项目。
词汇单元:即分词。
词干提取器,如Snowball。
搜索质量主要由查准率(Precision)和查全率(Recall)来衡量。
[1]P13 语法检查器: Lucene的 contrib目录提供了两个模块完成此功能。
查询对象: Lucene提供了一个称之为查询解析器(QueryParser),用它可以根据通用查询语法将用户输入的文本处理成查询对象。
查询搜索:�搜�检索索引并返回与�搜�语句匹配的文档,结果返回时按照�搜�请求来排序。
搜索查询组件涵盖了搜索引擎内部复杂的工作机制,Lucene正是如此,它为你完成这一切。
倒排索引:inverted index常见的搜索理论模型有如下3种。
■ 纯布尔模型(Pure Boolean model) 文档不管是否匹配查询请求,都不会被评分.在该模型下,匹配文档与评分不相关,也是无序的;一条查询仅获取所有匹配文档集合的一个子集。
■ 向量空间模型(Vector space model)查询语句和文档都是高维空间的向量模型,这里每一个独立的项都是一个维度。
查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到.■概率模型(Probabilistic model)在该模型中,采用全概率方法来计算文档和查询语句的匹配概率。
Lucene在实现上采用向量空间模型和纯布尔模型,并能针对具体搜索让你决定采用哪种模型。
最后,Lucene返回的文档结果必须用比较经济的方式展现给用户。
搜索范围:涉及分布式搜索,Apache Lucene项目下的Solr和Nutch项目提供了对索引拆分和复制的支持,另Katta和Elastic search。
lucene 原理Lucene原理。
Lucene是一个开源的全文检索引擎工具包,它提供了完整的查询引擎和索引引擎,主要用于实现全文检索功能。
它是由Apache软件基金会支持的一个全文检索引擎工具包,是一个全面的文本搜索引擎工具包,不仅提供了全文检索功能,还提供了索引和搜寻的功能。
Lucene的原理主要包括索引的建立和搜索的过程。
在索引的建立过程中,Lucene会将文档中的关键词提取出来,并进行分词处理,然后将分词后的关键词存储在倒排索引中。
在搜索的过程中,Lucene会根据用户输入的关键词,在倒排索引中查找相关的文档,然后返回给用户相关的搜索结果。
在Lucene的索引建立过程中,首先需要将文档进行分词处理,将文档中的关键词提取出来,并进行分词处理,将分词后的关键词存储在倒排索引中。
倒排索引是将文档中的每个关键词和包含该关键词的文档进行对应,这样可以快速地找到包含某个关键词的文档。
在搜索的过程中,用户输入的关键词会经过相同的分词处理,然后在倒排索引中查找相关的文档,最后返回给用户相关的搜索结果。
Lucene的搜索过程是通过查询解析器将用户输入的查询语句解析成查询对象,然后通过查询对象在倒排索引中查找相关的文档。
在倒排索引中查找文档时,Lucene会使用倒排列表和倒排索引的数据结构,通过倒排列表来快速定位包含查询关键词的文档。
然后根据倒排列表中的文档ID,去倒排索引中查找对应的文档内容,最后返回给用户相关的搜索结果。
总的来说,Lucene的原理主要包括索引的建立和搜索的过程。
在索引的建立过程中,Lucene会将文档进行分词处理,并将分词后的关键词存储在倒排索引中。
在搜索的过程中,Lucene会通过查询解析器将用户输入的查询语句解析成查询对象,然后在倒排索引中查找相关的文档,最后返回给用户相关的搜索结果。
通过了解Lucene的原理,可以更好地使用Lucene来实现全文检索功能。
Lucene入门课程计划:1、搜索引擎介绍2、Lucene介绍3、Lucene全文检索执行过程4、Lucene入门程序5、Lucene API详解6、Lucene对搜素结果排名1搜索引擎介绍1.1搜索引擎发展史●萌芽:Archie、Gopher●起步:Robot(网络机器人)的出现与spider(网络爬虫)●发展:excite、galaxy、yahoo●繁荣:infoseek,altaVista,Google和baidu1.2搜索的常见应用场景应用场景:1、单机软件的搜索(word中的搜索)2、站内搜索(baidu贴吧、论坛、京东、taobao)3、垂直领域的搜索(docin豆丁、拉勾、100offer)4、专业搜索引擎公司(google、baidu)1.3搜索数据方式1.3.1顺序扫描法所谓顺序扫描,例如要找内容包含一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。
这种方法是顺序扫描方法,数据量大就搜索慢。
1.3.2倒排索引倒排索引(也称为倒排文件)是一种存储了来自文本中的映射的索引数据结构。
比如单词或者数字,对应到它们在数据库、一个文件或者一组文件中的位置。
它是在文档检索系统中使用的最流行的数据结构,在搜索引擎中有大规模使用案例例如我们使用新华字典查询汉字,新华字典有偏旁部首的目录(索引),我们查字首先查这个目录,找到这个目录中对应的偏旁部首,就可以通过这个目录中的偏旁部首找到这个字所在的位置(文档)。
倒排索引做两件事情:1、提取资源中关键信息,建立索引(目录)2、搜索时,根据关键字(目录),找到资源的位置1.4倒排索引1.4.1相关术语文档(Document):一般搜索引擎处理的对象是互联网网页,对于搜索引擎来讲,Word、PDF、html、XML等不同格式的文件都可以称为文档,一般以文档来表示文本信息。
lucene写入原理Lucene是一个开源的全文检索引擎库,提供了高效的文本索引和搜索功能。
在本篇文章中,我们将深入探讨Lucene的写入原理。
一、索引结构Lucene的索引结构基于倒排索引(Inverted Index),它是一种将文档中的每个单词映射到包含该单词的文档的数据结构。
倒排索引的核心是词项表(Term Dictionary)和倒排表(Inverted List)。
词项表是一个有序的词典,它将每个词项映射到一个唯一的编号,该编号用于在倒排表中查找对应的倒排列表。
倒排表是一个包含倒排列表的数据结构,每个倒排列表记录了包含某个词项的文档编号以及该词项在文档中的位置信息。
二、写入过程1. 创建索引在Lucene中,创建索引的第一步是定义一个IndexWriter对象,并通过IndexWriterConfig来配置索引的一些属性,如分词器(Analyzer)、索引路径等。
接下来,我们可以通过IndexWriter 的addDocument方法将文档添加到索引中。
2. 文档处理在添加文档到索引之前,需要将文档进行处理,将其拆分为一系列的字段(Field)。
每个字段包含一个字段名和对应的字段值。
通常,我们可以将文档的标题、内容、作者等信息作为字段添加到索引中。
3. 分词器分词器(Analyzer)是Lucene中的一个关键组件,它负责将文本进行分词处理。
在Lucene中,有多种分词器可供选择,如标准分词器(StandardAnalyzer)、中文分词器(SmartChineseAnalyzer)等。
分词器将文本拆分为一个个的词项,并删除一些常见的停用词(如“的”、“是”等),以提高索引的查询效果。
4. 倒排索引写入当文档经过分词处理后,倒排索引的写入过程开始。
Lucene会将文档中的每个词项添加到词项表中,并生成对应的倒排列表。
倒排列表中记录了包含该词项的文档编号以及词项在文档中的位置信息。
5. 磁盘写入在倒排索引写入完成后,Lucene将倒排索引的数据写入磁盘。
前沿写这点文字是面向lucene初中级用户,站在一个编辑加工的角度,对lucene进行解释,使抽象的概念更容易被大家理解,也尽可能节省大家搜集资料之苦,在这里广纳资源,采其精华,供大家分享。
一、背景简介Lucene 是一个基于 Java 的全文检索工具包,你可以利用它来为你的应用程序加入索引和检索功能。
Lucene 目前是著名的 Apache Jakarta 家族中的一个开源项目/lucene/,很多Java项目都使用了Lucene作为其后台的全文索引引擎,比较著名的有:∙Jive:WEB论坛系统;∙Eyebrows:邮件列表HTML归档/浏览/查询系统,本文的主要参考文档“TheLucene search engine: Powerful, flexible, and free”作者就是EyeBrows系统的主要开发者之一,而EyeBrows已经成为目前APACHE项目的主要邮件列表归档系统。
∙Cocoon:基于XML的web发布框架,全文检索部分使用了Lucene ∙Eclipse:基于Java的开放开发平台,帮助部分的全文索引使用了Lucene∙IBM社区:网站的搜索功能。
对于中文用户来说,最关心的问题是其是否支持中文的全文检索。
但通过后面对于Lucene的结构的介绍,你会了解到由于Lucene良好架构设计,对中文的支持只需对其语言词法分析接口进行扩展就能实现对中文检索的支持。
二、demo运行1、demo的配置目前最新的版本是lucene-2.2.0 ,下载解压后(或附件包中)看到luceneweb.war,lucene-demos-2.2.0.jar,lucene-core-2.2.0.jar三个文件。
0).自持demo运行:在环境变量classpath里面配置加入lucene-demos-2.2.0.jar,lucene-core-2.2.0.jar的存放路径。
手工在C盘根目录下面建立目录luceneindex(存放索引文件),demo(用来测试的文件,放入一些html、text 文件)。
放到其他位置也可以,只是在下面执行命令的路径处作相应更改。
转到cmd工作模式下,打入命令:(创建测试文件的索引文件)java org.apache.lucene.demo.IndexHTML –create –index ./c://luce neindex ./ c://demoOK!如果看到adding /usr/local/man/man1/mysql.1...........adding /usr/local/man/man1/cvs.11614 total milliseconds就会将demo目录下的文件建立索引,并将索引文件存到luceneindex目录下面。
打入命令:(检索索引文件)java org.apache.lucene.demo.SearchFiles出现Query:OK!Lucene自待的demo运行成功,输入检索值,如果你的测试文档中有相关关键字即可出现如下类似结果Query: passwordSearching for: password7 total matching documents0. /usr/local/man/man1/mysql.1......6. /usr/local/man/man1/mysqlshow.11)、luceneweb.war的运行:luceneweb.war复制到tomcat的webapp目录下,假定tomcat装在$TOMCATHOME目录下,具体应用时用真实的目录替换$TOMCATHOME。
cd $TOMCATHOME/webappsmkdir lucenedbcd lucenedbjava org.apache.lucene.demo.IndexHTML -create -index$TOMCAT/webapps/lucenedb ../examples<--用相对路径“..”,一来指明被索引的文件的位置,二来用来显示被索引文件的URL,因为检索的jsp程序在luceneweb子目录下.examples可用其它的真实应用的目录名来替换cd ..cp~/lucene-1.2/luceneweb.war . <--luceneweb.war在你解压缩生成的lucene-1.2目录下../bin/shudown.sh../bin/startup.sh然后通过客户端访问:8080/luceneweb,如果顺利浏览器应出现右边所示的内容。
.再到服务器端cd lucenewebvi configuration.jsp <--将indexLocation 的值改为"$TOMCATHOME/webapps/lucenedb";cd ..jar -ur luceneweb.war luceneweb再到客户端,刷新刚才的页面,然后就可以输入单词进行检索了。
2、原理分析0)设有两篇文章1和2文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.文章2的内容为:He once lived in Shanghai.1)全文分析:由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。
英文单词由于用空格分隔,比较好处理。
中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”e.文章中的标点符号通常不表示某种概念,也可以过滤掉在lucene中以上措施由Analyzer类完成经过上面处理后文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou] 文章2的所有关键词为:[he] [live] [shanghai]2) 倒排索引:有了关键词后,我们就可以建立倒排索引了。
上面的对应关系是:“文章号”对“文章中所有关键词”。
倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。
文章1,2经过倒排后变成关键词文章号guangzhou 1he 2i 1live 1,2shanghai 2tom 1通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene 中记录的就是这种位置。
加上“出现频率”和“出现位置”信息后,我们的索引结构变为:以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。
以上就是lucene索引结构中最核心的部分。
我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。
其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url 中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
为了减小索引文件的大小,Lucene对索引还使用了压缩技术。
首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。
其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。
例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。
注意是“上一个词”。
由于词典是按顺序排列的,这种压缩方法的效果会非常显著。
下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词“live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。
词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。
全文检索框架的实现机制:Lucene的API接口设计的比较通用,输入输出结构都很像数据库的表==>记录==>字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。
总体上看:可以先把Lucene当成一个支持全文索引的数据库系统。
比较一下Lucene和数据库:全文检索≠ like "%keyword%"由于数据库索引不是为全文索引设计的,因此,使用like "%keyword%"时,数据库索引是不起作用的,在使用like查询时,搜索过程又变成类似于一页页翻书的遍历过程了,所以对于含有模糊查询的数据库服务来说,LIKE对性能的危害是极大的。
如果是需要对多个关键词进行模糊匹配:like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了。
通常比较厚的书籍后面常常附关键词索引表(比如:北京:12, 34页,上海:3,77页……),它能够帮助读者比较快地找到相关内容的页码。
而数据库索引能够大大提高查询的速度原理也是一样,想像一下通过书后面的索引查找的速度要比一页一页地翻内容高多少倍……而索引之所以效率高,另外一个原因是它是排好序的。