Lucene3.0之搜索

合集下载

Lucene索引和搜索过程核心类详解【基础】

Lucene索引和搜索过程核心类详解【基础】

Lucene索引和搜索过程核心类详解【基础】Lucene 索引和搜索过程核心类详解索引核心类1、IndexWriter(写索引)2、Directory(索引存放位置)3、Analyzer(分析器)4、document(文档)5、Field(域)搜索核心类1、IndexSearcher(搜索引)2、Term(搜索功能基本单元)3、Query(查询)4、TermQuery(Query 子类最基本查询类型)5、TopDocs(指针容器)IndexWriterIndexWriter是在索引过程中的中心组件。

这个类创建一个新的索引并且添加文档到一个已有的索引中。

它可以对索引进行添、删、更新操作,但是不能读取或搜索。

添加方法addDocument (Document)加Document使用默认的分词器addDocument (Document, Analyzer)加入的时候使用指定的分词器删除方法deleteDocuments (Term);deleteDocuments (Term[]);deleteDocuments (Query);deleteDocuments (Query[]);一般最好有个唯一索引,这样才好删,不然的话有可以会一删一大堆如:writer.deleteDocument(new Term(“ID”, documentID));更新方法注意:更新索引也提供两个方法,其实Lucene是没有办法更新的,只有先删除了再更新,updateDocument (Term, Document);如:writer.updateDocument(new Term(“ID”, documenteId), newDocument);updateDocument (Term, Document, Analyzer)DirectoryDirectory类代表一个Lucene索引的位置。

它是一个抽象类,允许它的子类(其中的两个包含在Lucene中)在合适时存储索引。

全文检索原理及Lucene实现之搜索

全文检索原理及Lucene实现之搜索

全文检索原理及Lucene实之搜索研发中心胡启稳/文搜索处理过程经过前面构建索引的一系列过程,终于到了我们的全文检索的最终目标:搜索。

现在的问题看起来很简单,输入我们的待查询关键字然后在索引里面找到结果返回不就可以了吗?但是问题并不象看起来的那么简单,搜索的处理过程如下:第一步:用户输入查询语句查询语句同普通的语言一样,也是有定的语法的。

不同的查询语句有不同的语法,如SQL 语句、HQL语句等。

查询语句的语法根据全文检索引擎的实现不同而不同。

最基本的有比如:AND、OR、NOT等。

举个例子,用户你输入语句:“Lucene AND learned NOT hadoop”,说是用户想找的是包含“Lucene”和“learned”但不包括“hadoop”的文档。

第二步:对查询语句进入词法分析、语法分析及语言处理由于查询语句有语法,因而也要进行词法分析、语法分析及语言处理1.词法分析主要用来识别单词和关键字。

如上述例子中,经过词法分析,得到的词有“lucene”“learned”“hadoop”关键字有“AND”“NOT”。

如果在词法分析中发现不合法的关键字,则会出现广错误,如上面中的AND,如果用户不小心拼成AMD,则AMD会作为一个普通的单词参与查询2.语法分析主要是根据查询语句的语法规则来形成一棵语法树如果发现查询语句不满足语法规划,则会报错。

如“luceneNOT AND learned”,则会出错。

如上述例子,“门户AND 开发NOT 实施”,则会形成以下语法树:3. 语言处理同索引过程中的语言处理几乎相同。

如learned变成learn等。

经过第二步,我们得到一棵经过语言处理的语法树。

第三步:搜索索引,得到符合语法树的文档。

此步骤有分几小步:1.首先,在反向索引表中,分别找出包含lucene,learn,hadoop的文档链表。

2.其次,对包含lucene,learn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。

lucene实现全文搜索

lucene实现全文搜索

lucene实现全文搜索1.什么是全文搜索全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

这个过程类似于通过字典中的检索字表查字的过程。

2.什么是luceneapache lucene是一个开放源程序的搜寻器引擎,利用它可以轻易地为Java软件加入全文搜寻功能。

lucene的最主要工作是替文件的每一个字作索引,索引让搜寻的效率比传统的逐字比较大大提高,lucene提供一组解读,过滤,分析文件,编排和使用索引的API,它的强大之处除了高效和简单外,是最重要的是使使用者可以随时应自已需要自订其功能。

lucene是apache软件基金会项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。

lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。

3.特点及优势lucene作为一个全文检索引擎,其具有如下突出的优点:1、索引文件格式独立于应用平台。

lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。

2、在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。

然后通过与原有索引的合并,达到优化的目的。

3、优秀的面向对象的系统架构,使得对于lucene扩展的学习难度降低,方便扩充新功能。

4、设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。

5、已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。

Lucene教程详解

Lucene教程详解

Lucene教程详解Lucene-3.0.0配置一、Lucene开发环境配置step1.Lucene开发包下载step2.Java开发环境配置step3.Tomcat安装step4.Lucene开发环境配置解压下载的lucene-3.0.0.zip,可以看到lucene-core-3.0.0.jar和lucene-demos-3.0.0.jar这两个文件,将其解压(建议放在安装jdk的lib文件夹内),并把路径添加到环境变量的classpath。

二、Lucene开发包中Demo调试控制台应用程序step1.建立索引>java org.apache.lucene.demo.IndexFiles [C:\Java](已经存在的任意文件路径)将对C:\Java下所有文件建立索引,同时,在当前命令行位置将生成“index”文件夹。

step2.执行查询>java org.apache.lucene.demo.SearchFiles将会出现“Query:”提示符,在其后输入关键字,回车,即可得到查询结果。

Web应用程序step1.将lucene-core-3.0.0.jar和lucene-demos-3.0.0jar这两个文件复制到安装Tomcat 的\common\lib中step2.解压下载的lucene-3.0.0.zip,可以看到luceneweb.war文件。

将该文件复制到安装Tomcat的\webappsstep3.重启Tomcat服务器。

step4.建立索引>java org.apache.lucene.demo.IndexHTML -create -index [索引数据存放路径] [被索引文件路径](如:D:\lucene\temp\index D:\lucene\temp\docs)step5.打开安装Tomcat的\webapps\luceneweb\configuration.jsp文件,找到String indexLocation = "***",将"***"改为第四步中[索引数据存放路径],保存关闭。

lucene全文检索精华

lucene全文检索精华

lucene全文检索精华lucene全文检索1 概念全文检索(Full-Text Retrieval)是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。

当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程.1.1 lucene全文检索的特性全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。

全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索的特性,我们要知道:1,只处理文本。

2,不处理语义。

3,搜索时英文不区分大小写。

4,结果列表有相关度排序。

下图就是显示“1+1等于几”这个搜索要求对应的结果。

可以看到,是没有“2”这个结果的,结果页面都是出现了这些词的网页 .1.2 全文检索的应用场景我们使用Lucene,主要是做站内搜索,即对一个系统内的资源进行搜索。

如BBS、BLOG中的文章搜索,网上商店中的商品搜索等。

使用Lucene的项目有Eclipse、Jira等。

一般不做互联网中资源的搜索,因为不易获取与管理海量资源(专业搜索方向的公司除外)。

2 第一个lunece程序2.1 准备lucene的开发环境搭建Lucene的开发环境只需要加入Lucene的Jar包,要加入的jar包至少要有: ? lucene-core-4.4.0.jar(核心包)? analysis\\common\\lucene-analyzers-common-4.4.0.jar(分词器) ?highlighter\\lucene-highlighter-4.4.0.jar(高亮) ? \\memory\\lucene-memory-4.4.0.jar(高亮)? queryparser\\ lucene-queryparser-4.4.0.jar (查询解析)2.2 实现建立索引功能(IndexWriter)/*** 使用indexWriter对数据库建立索引.. * @throws IOException */ @Test public void createIndex() throws IOException{//索引存放的位置...Directory directory=FSDirectory.open(new File(\));//lucene当前使用的匹配版本Version matchVersion=Version.LUCENE_44;//分词器,对文本进行分词,抽象类,由子类实现不同的分词方式Analyzer analyzer=new StandardAnalyzer(matchVersion); //索引写入的配置 IndexWriterConfig indexWriterConfig=new//构建用于操作索引的类IndexWriter indexWriter=new IndexWriter(directory,IndexWriterConfig(matchVersion, analyzer);indexWriterConfig);//索引库里面的要遵守一定的结构,(索引结构...) 在索引库当中保存的都是documentDocument doc=new Document(); //索引document里面页游很多的字段... /** * 1:字段的名称 * 2:字段对应的值* 3:该字段在索引库中是否存储 */IndexableField id=new IntField(\, 1, Store.YES);//StringField不会根据分词器去拆分,只有后面的String全包括才能被搜索到IndexableField title=new StringField(\, \培训,传智播客//TextField如果按照默认分词器去拆分,中文则是按照单个中文拆分的专注Java培训10年\, Store.YES);IndexableField content=new TextField(\, \培训的龙头老大,口碑最好的java培训机构,进来看看同学们的呐喊\, Store.YES);doc.add(id);}doc.add(title); doc.add(content);indexWriter.addDocument(doc);indexWriter.close();2.3 实现搜索功能(IndexSearcher)/*** 使用indexSearcher对数据进行搜索 * @throws IOException */ @Testpublic void queryIndex() throws IOException{//索引存放的位置Directory directory=FSDirectory.open(new File(\)); //创建索引读取器IndexReader indexReader=DirectoryReader.open(directory);//通过indexSearcher去检索索引目录...IndexSearcher indexSearcher=new IndexSearcher(indexReader);//我们以后只要根据索引查找,整个过程肯定要分2次..//这是一个搜索条件..,通过定义条件来进行查找...(可以拿到编号,编号都放在了//term 我需要根据哪个字段进行检索,字段对应的值...//Query是抽象类,由子类去实现不同的查询规则Query query=new TermQuery(new Term(\, \));//搜索先搜索索引目录(第一次搜)..不会直接搜索到document(第二次搜) //找到符合query条件的前面N条记录...如果不加条件则会全部查询出来ScoreDoc数组中,遍历数组就获得了编号)TopDocs topDocs=indexSearcher.search(query, 10); System.out.println(\总记录数是:\+topDocs.totalHits);//返回结果的数组(得分文档)ScoreDoc[] scoreDocs=topDocs.scoreDocs; //返回一个击中..for(ScoreDoc scoreDoc:scoreDocs){int docID=scoreDoc.doc; //根据编号去击中对应的文档//lucene的索引库里有很多document,lucene为每个document定义一个编号,唯一标识(docId),是自增长的。

关于lucene的IndexSearcher单实例,对于索引的实时搜索

关于lucene的IndexSearcher单实例,对于索引的实时搜索

关于lucene的IndexSearcher单实例,对于索引的实时搜索Lucene版本:3.0⼀般情况下,lucene的IndexSearcher都要写成单实例,因为每次创建IndexSearcher对象的时候,它都需要把索引⽂件加载进来,如果访问量⽐较⼤,⽽索引也⽐较⼤,那就很容易造成内存溢出!但是如果仅仅按照⼀般的单实例来写的话,如果更新了索引,那么在不重启服务的情况下,Searcher对象是搜索不到索引更新后的内容的.如何解决呢,这⾥给出⼀个⽅法!在这个⽅法⾥,建造了⼀个Factory类,分别管理IndexReader和IndexSearcher的单实例.import java.io.File; import java.io.IOException; import java.util.Date; import org.apache.lucene.index.CorruptIndexException; importorg.apache.lucene.index.IndexReader; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.store.SimpleFSDirectory; /** * ⼯⼚类,负责管理IndexReader、IndexSearcher * @author .K' */ public class LuceneFactory { private static IndexReader reader = null; private static IndexSearcher searcher = null; /** *获得IndexReader对象,判断是否为最新,不是则重新打开 (以下省略了try...catch) *@param file 索引路径的File对象*@return IndexReader对象 **/ public static synchronized IndexReader getIndexReader(File file){ if (reader == null) { reader =IndexReader.open(SimpleFSDirectory.open(file)); } else { if(!reader.isCurrent()){ reader = reader.reopen(); } } return reader; } /** * 获得IndexSearcher对象,判断当前的Searcher中reader是否为最新,如果不是,则重新创建IndexSearcher(省略了try...catch) * @param reader * IndexReader对象 * @return IndexSearcher对象 */ public static synchronized IndexSearcher getIndexSearcher(IndexReader reader) { if (searcher == null) { searcher = new IndexSearcher(reader); }else{ IndexReader r = searcher.getIndexReader(); if(!r.isCurrent()){ searcher = new IndexSearcher(reader); } } return searcher; } }调⽤⼯⼚类中的⽅法创建Searcher。

Lucene搜索方法总结

Lucene搜索方法总结

1.多字段搜索使用multifieldqueryparser可以指定多个搜索字段。

query query = multifieldqueryparser.parse(”name*”, new string[] { fieldname, fieldvalue }, analyzer);indexreader reader = indexreader.open(directory);indexsearcher searcher = new indexsearcher(reader);hits hits = searcher.search(query);2.多条件搜索除了使用queryparser.parse分解复杂的搜索语法外,还可以通过组合多个query来达到目的。

query query1 = new termquery(new term(fieldvalue,“name1′)); //词语搜索query query2 = new wildcardquery(new term(fieldname,“name*”)); //通配符//query query3 = new prefixquery(new term(fieldname,“name1′)); //字段搜索field:keyword,自动在结尾添加*//query query4 = new rangequery(new term(fieldnumber, numbertools.longtostring(11l)), new term(fieldnumber, numbertools.longtostring(13l)), true); //范围搜索//query query5 = new filteredquery(query, filter); //带过滤条件的搜索booleanquery query = new booleanquery();query.add(query1, booleanclause.occur.must);query.add(query2, booleanclause.occur.must);indexsearcher searcher = new indexsearcher(reader);hits hits = searcher.search(query);3.过滤使用filter对搜索结果进行过滤,可以获得更小范围内更精确的结果。

lucene-Android

lucene-Android

Lunene在Android sqlite数据库搜索中的应用Lucene是一套用于全文检索和搜寻的开源程式库,供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。

在Java开发环境里Lucene是一个成熟的免费开源工具,Lucene 使用Java语言写成的,因而就可以应用到Android开发上。

此处采用的Lucene版本为3.0.3。

一.在项目下导入需要的包(一开始我分别采用4.2和4.0版本,发现调试时连接不上模拟器或手机,对比一下4.2,4.0的包对于3.0大了一倍多,有一个达到了2M多,3.0的包没有一个超过1M。

难道是libs 下的包大小有限制吗?或者其他原因,当时搞了很久都没想清楚。

总之换成3.0.3的就好了,其他的版本没有试过).二.为sqlite数据库创建索引public class Search {private MySQLiteHelper databaseHelper;private SQLiteDatabase db;private Directory dir;private String path;public Search(Context context) {this.context = context;try {path=android.os.Environment.getExternalStorageDirectory() + "/"+ context.getPackageName() + "/files/";//在SD卡上创建文件,如果没有SD卡则不会成功。

dir = new SimpleFSDirectory(new File(path));//获取路径下的目录new Thread(new Runnable() {public void run() {index();}}).start();} catch (IOException e) {e.printStackTrace();}}private void index() {/*** 在sd卡上创建与数据库相关的索引* */try {databaseHelper = new MySQLiteHelper(this.context);db = databaseHelper.getWritableDatabase();Cursor cursor = db.rawQuery("select * from "+ MySQLiteHelper.SEARCH_TABLE+ " where 1=1", null);IndexWriter indexWriter = new IndexWriter(dir,new StandardAnalyzer(Version.LUCENE_30), true,IndexWriter.MaxFieldLength.UNLIMITED);while (cursor.moveToNext()) {//创建索引,保存到SD卡path路径下Document doc = new Document();doc.add(new Field("title", cursor.getString(cursor.getColumnIndex("title")), Field.Store.YES,Field.Index.ANALYZED));doc.add(new Field("content", cursor.getString(cursor.getColumnIndex("content")), Field.Store.YES,Field.Index.ANALYZED));indexWriter.addDocument(doc);}indexWriter.optimize();indexWriter.close();cursor.close();db.close();databaseHelper.close();} catch (CorruptIndexException e) {e.printStackTrace();} catch (LockObtainFailedException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}三.搜索文本内容/*** 在索引上搜索最佳文本.field表示要搜索的数据库字段,content表示搜索的内容* */private void doSearch(String field, String content) { IndexSearcher indexSearch;TopDocs hits = null;Document doc = null;ScoreDoc sdoc;try {indexSearch = new IndexSearcher(dir);// 创建QueryParser对象,第一个参数表示Lucene的版本,第二个表示搜索Field的字段,第三个表示搜索使用分词器QueryParser queryParser=new QueryParser(Version.LUCENE_30, field,new StandardAnalyzer(Version.LUCENE_30));Query query = queryParser.parse(content);// 搜索结果 TopDocs里面有scoreDocs[]数组,里面保存着索引值hits = indexSearch.search(query, 10);// hits.totalHits表示一共搜到多少个Log.i("search", Integer.toString(hits.totalHits));// 循环hits.scoreDocs数据,并使用indexSearch.doc方法把Document还原,再拿出对应的字段的值for (int i=0;i<hits.scoreDocs.length-1;i++) {sdoc = hits.scoreDocs[i];doc = indexSearch.doc(sdoc.doc);Log.i("title",doc.get("title").toString());Log.i("content",doc.get("content").toString());}indexSearch.close();} catch (CorruptIndexException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ParseException e) {e.printStackTrace();}}例如,我要搜索内容为“大家好!”的字段则调用doSearch("content","大家好"); 在Log中可以看到与内容为“大家好!”相关分词搜索的结果。

一步一步跟我学习lucene(8)---lucene搜索之索引的查询原理和查询工具类

一步一步跟我学习lucene(8)---lucene搜索之索引的查询原理和查询工具类

一步一步跟我学习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.}。

Lucene学习总结之四:Lucene索引过程分析(1)

Lucene学习总结之四:Lucene索引过程分析(1)

对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后的文章中进行分析。

Lucene的索引过程,很多的博客,文章都有介绍,推荐大家上网搜一篇文章:《Annotated Lucene》,好像中文名称叫《Lucene源码剖析》是很不错的。

想要真正了解Lucene索引文件过程,最好的办法是跟进代码调试,对着文章看代码,这样不但能够最详细准确的掌握索引过程(描述都是有偏差的,而代码是不会骗你的),而且还能够学习Lucene的一些优秀的实现,能够在以后的工作中为我所用,毕竟Lucene是比较优秀的开源项目之一。

由于Lucene已经升级到3.0.0了,本索引过程为Lucene 3.0.0的索引过程。

一、索引过程体系结构Lucene 3.0的搜索要经历一个十分复杂的过程,各种信息分散在不同的对象中分析,处理,写入,为了支持多线程,每个线程都创建了一系列类似结构的对象集,为了提高效率,要复用一些对象集,这使得索引过程更加复杂。

其实索引过程,就是经历下图中所示的索引链的过程,索引链中的每个节点,负责索引文档的不同部分的信息,当经历完所有的索引链的时候,文档就处理完毕了。

最初的索引链,我们称之基本索引链。

为了支持多线程,使得多个线程能够并发处理文档,因而每个线程都要建立自己的索引链体系,使得每个线程能够独立工作,在基本索引链基础上建立起来的每个线程独立的索引链体系,我们称之线程索引链。

线程索引链的每个节点是由基本索引链中的相应的节点调用函数addThreads创建的。

为了提高效率,考虑到对相同域的处理有相似的过程,应用的缓存也大致相当,因而不必每个线程在处理每一篇文档的时候都重新创建一系列对象,而是复用这些对象。

所以对每个域也建立了自己的索引链体系,我们称之域索引链。

域索引链的每个节点是由线程索引链中的相应的节点调用addFields 创建的。

Lucene3.0的主要变化

Lucene3.0的主要变化

一、概述Lucene3.0(以下简称3.0)已于2009-11-25发布,3.0版本是重大的版本,改动很大。

在API上做了很多的调整,已经删除了很多之前废弃的方法以及类,并支持了很多Java5 的新特性:包括泛型、可变参数、枚举和autoboxing等。

因此,此版本和2.x版本不能兼容,如要使用3.0版本,最好是在新项目中去使用,而不是去升级2.x或之前的版本!二、2.9版本介绍由于新版本变动很大,官方是不推荐从旧版本升级到新版本的。

因为改动会很大。

其实在2.9版本时改动就很大,因为2.9版本就是为3.0做准备的,但是为了向下兼容,2.9并没有抛弃之前的旧方法,所以可以直接向下兼容。

2.9版本主要是在性能方面的优化,包括在Lucene对Lucene底层的内部结构改进、索引的管理方式等多个方面。

1、索引文件改进Lucene的索引数据是存放在独立的文件中的,这些文件就是存储着索引数据库一些列分离的“片段”。

当我们想索引中增加文档时,便会不断的创建一些可以合并的新片段,因为读写文件的开销比较大,因此这些字段信息Lucene并非每次都直接加到索引文件里面去,而是先缓存,等到一定量的时候再一次写到文件中。

在2.9以后,Lucene会为每个片段分别管理FieldCache以此避开跨片段加载FieldCatch的需求,这样就解决了Lucene跨片段加载FieldCatch的效率很低下问题,这个改动大为提高了性能。

Lucid Imagination的Mark Miller 运行了一个简单的性能测试,表明在5,000,000个不同字符串下的情况下,Lucene 相对于2.4版本会获得15倍左右的性能提高: Lucene 2.4: 150.726s Lucene 2.9: 9.695s2、重开搜索新版本引入了IndexWriter.getReader()方法,它可用于搜索目前完整的索引,包括当前 IndexWriter会话中还没有提交的改变,这带来了接近于实时搜索的能力。

全文检索lucene研究

全文检索lucene研究

全文检索lucene研究本文由美白面膜排行榜/doc/4616316215.html,整理全文检索lucene研究1 Lucene简介Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。

Lucene以其方便使用、快速实施以及灵活性受到广泛的关注。

它可以方便地嵌入到各种应用中实现针对应用的全文索引、检索功能,本总结使用lucene3.0.02 Lucene 的包结构1、analysis对需要建立索引的文本进行分词、过滤等操作2、standard是标准分析器3、document提供对Document和Field的各种操作的支持。

4、index是最重要的包,用于向Lucene提供建立索引时各种操作的支持5、queryParser提供检索时的分析支持6、search负责检索7、store提供对索引存储的支持8、util提供一些常用工具类和常量类的支持Lucene中的类主要组成如下:1)org.apache.1ucene.analysis语言分析器,主要用于的切词Analyzer是一个抽象类,管理对文本内容的切分词规则。

2)org.apache.1uceene.document索引存储时的文档结构管理,类似于关系型数据库的表结构。

3)document包相对而言比较简单,document相对于关系型数据库的记录对象,Field主要负责字段的管理。

4)org.apache.1ucene.index索引管理,包括索引建立、删除等。

索引包是整个系统核心,全文检索的根本就是为每个切出来的词建索引,查询时就只需要遍历索引,而不需要去正文中遍历,从而极大的提高检索效率。

5)org.apache.1ucene.queryParser查询分析器,实现查询关键词间的运算,如与、或、非等。

6)org.apache.1ucene.search检索管理,根据查询条件,检索得到结果。

7)org.apache.1ucene.store数据存储管理,主要包括一些底层的I/0操作。

lucene3.0创建索引及多目录搜索详解

lucene3.0创建索引及多目录搜索详解

lucene3.0 创建索引及多目录搜索详解最近项目中用到了 Lucene3.0, 如下:创建索引: Java codepublic void index() throwsCorruptIndexException,LockObtainFailedException, IOException { // 索引目录File indexDir = newFile("D:/workspace/code/java/TestLucene3/index/txt/test/") // 注意:这里建立索引用的分词方法,在搜索时分词也应该 采用同样的分词方法。

不然搜索数据可能会不正确// 使用 Lucene 自带分词器Analyzer luceneAnalyzer = newStandardAnalyzer(Version.LUCENE_CURRENT);)和 RAMDirectory (存储到内存中) ,// 第一个参数是存放索引文件位置, 第二个参数是使用的 分词方法, 第三个: true ,建立全新的索引, false, 建立增 量索引。

// IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer, true);// 第一个参数是存放索引目录有 FSDirectory (存储到磁盘第二个参数是使用的分词器, 第三个: true ,建立全新的索引, 增量索引,第四个是建立的索引的最大长度。

IndexWriter indexWriter = newIndexWriter(FSDirectory.open(indexDir), luceneAnalyzer, true, IndexWriter.MaxFieldLength.LIMITED);// 索引合并因子// SetMergeFactor (合并因子)// SetMergeFactor 是控制 segment 合并频率的,其决定了 个索引块中包括多少个文档,当硬盘上的索引块达到多少 时,// 将它们合并成一个较大的索引块。

Lucene 3.0.2 代码 分析

Lucene 3.0.2 代码 分析

全文检索与Lucene学习全文检索与Lucene学习本文是我最近针对Lucene3.3.0进行的总结,并提供了大量的实现Demo,常用的基本都有,下载地址:/detail/a_2cai/35941541 概述概念:Lucene不是一个完整的全文索引应用,而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。

当前的版本有:Java版的,.NET版的(不完全),网上也有C++重写的,其他各类语言大部分也都有重写的。

简单地说它就两个功能:索引和检索。

主要应用:全文检索,顾名思义即在文件文本中搜索是否含有某个词之类的。

(实质不一定是大文本)全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

这个过程类似于通过字典中的检索字表查字的过程。

全文检索使用的理由:执行模糊查询都需要对全表扫描或索引扫描意味着消耗大量IO,如果模糊查询经常发生,会造成数据库性能恶化。

(当然不一定非得是对大文件的检索,字段的模糊检索也是如此)通常比较厚的书籍后面常常附关键词索引表(比如:北京:12, 34页,上海:3,77页……),它能够帮助读者比较快地找到相关内容的页码。

而数据库索引能够大大提高查询的速度原理也是一样,想像一下通过书后面的索引查找的速度要比一页一页地翻内容高多少倍……而索引之所以效率高,另外一个原因是它是排好序的。

对于检索系统来说核心是一个排序问题。

由于数据库索引不是为全文索引设计的,因此,使用like "%keyword%"时,数据库索引是不起作用的,在使用like查询时,搜索过程又变成类似于一页页翻书的遍历过程了,所以对于含有模糊查询的数据库服务来说,LIKE对性能的危害是极大的。

如果是需要对多个关键词进行模糊匹配:like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了。

lucene搜索实现过程详解

lucene搜索实现过程详解

lucene搜索实现过程详解郭玉璞2008-05-05一.文档说明1.关于lucene索引生成过程和生成文件结构,在《关于lucene建立索引的详细过程及相关文件结构》一文中已经说明,本文涉及到的文件结构,请参考该文档,这里不再累赘,并且我们假设您已经对索引文件格式有了一定的了解。

2.为了对搜索的实现过程有一个清晰的认识,本文采用分级的形势,层层深入。

3.对于分词这一块,将有专题讲解,本文在不影响理解的情况下,没有详解。

二.搜索过程简介索引的过程主要分为以下几个步骤:1.打开索引文件,并将索引文件的相关信息读入。

代码如下:IndexReader reader = IndexReader.Open("index");其中,index为索引文件所在的文件夹名称。

该句执行完以后,索引文件的相关信息将存放在reader中。

2.实例化IndexSearcher,以便于后面的搜索操作。

代码如下:IndexSearcher searcher = new IndexSearcher(reader);该句执行完后,索引文件信息将存放在searcher中,后面的的搜索将运用searcher,而不是运用reader。

当然,初始化方式有很多种,这里就以代码所示为例。

3.声明查询分析器QueryPaser。

代码如下:QueryParser parser = new QueryParser(field, analyzer);其中,field为要查询的字段,analyzer为所选择的分析器。

4.设置Query间的逻辑关系。

代码如下:parser.SetDefaultOperator(QueryParser.Operator.AND);该句的功能是,如果用户以空格隔开两个字符串,设置这两个字符串之间的关系,代码所示的是与的关系,根据需要也可以设置成OR等关系。

此句可有可无,Lucene默认的是OR的关系。

5.生成Query子对象。

Lucene检索数据库支持中文检索

Lucene检索数据库支持中文检索

全文分两部分:一:Lucene简介Lucene版本:3.0.2全文检索大体分两个部分:索引创建(Indexing)和搜索索引(Search)1. 索引过程:1) 有一系列被索引文件(此处所指即数据库数据)2) 被索引文件经过语法分析和语言处理形成一系列词(Term)。

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

2. 搜索过程:a) 用户输入查询语句。

b) 对查询语句经过语法分析和语言分析得到一系列词(Term)。

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。

e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

• 索引过程如下:◦创建一个IndexWriter用来写索引文件,它有几个参数,INDEX_DIR 就是索引文件所存放的位置,Analyzer便是用来对文档进行词法分析和语言处理的。

◦创建一个Document代表我们要索引的文档。

◦将不同的Field加入到文档中。

我们知道,一篇文档有多种信息,如题目,作者,修改时间,内容等。

不同类型的信息用不同的Field来表示,在本例子中,一共有两类信息进行了索引,一个是文件路径,一个是文件内容。

其中FileReader的SRC_FILE就表示要索引的源文件。

◦ IndexWriter调用函数addDocument将索引写到索引文件夹中。

• 搜索过程如下:◦IndexReader将磁盘上的索引信息读入到内存,INDEX_DIR就是索引文件存放的位置。

◦创建IndexSearcher准备进行搜索。

◦创建Analyer用来对查询语句进行词法分析和语言处理。

◦创建QueryParser用来对查询语句进行语法分析。

◦QueryParser调用parser进行语法分析,形成查询语法树,放到Query 中。

Lucene搜索引擎框架基础实践

Lucene搜索引擎框架基础实践

Lucene 搜索引擎框架基础实践Lucene搜索引擎11) 有一系列被索引文件2) 被索引文件经过语法分析和语言处理形成一系列词(Term)。

3) 经过索引创建形成词典和反向索引表。

4) 通过索引存储将索引写入硬盘。

a) 用户输入查询语句。

b) 对查询语句经过语法分析和语言分析得到一系列词(Term)。

c) 通过语法分析得到一个查询树。

d) 通过索引存储将索引读入到内存。

e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

f) 将搜索到的结果文档对查询的相关性进行排序。

g) 返回查询结果给用户。

2lucene索引的单元对象是Document,它可以是一个文本、一封email或者一个网页等,其中Document包含多个Field,一个Field就是它的一个属性,比如“文件路径”、“作者”,“文件内容”等都是Field1)索引用类:/*** 对目录进行Lucene索引* @author roy**/public class Indexer {private static String INDEX_DIR = "G:\\ROY的各种笔记\\索引"; // 索引结果存放目录private static String DATA_DIR = "G:\\ROY的各种笔记"; //被索引文件存放的目录/*** 测试主函数* @param args* @throws Exception*/public static void main(String[] args) throws Exception{long start = new Date().getTime();int numIndexed = index(new File(INDEX_DIR),new File(DATA_DIR));//调用index方法long end = new Date().getTime();System.out.println("Indexing " + numIndexed + " files took " + (end - start) + " milliseconds");}/*** 索引dataDir下的.txt文件,并储存在indexDir下,返回索引的文件数量* @param indexDir* @param dataDir* @return* @throws IOException*/private static int index(File indexDir, File dataDir) throws Exception{if(!dataDir.exists() || !dataDir.isDirectory()){throw new Exception("被索引的文件不存在!");}if(!indexDir.exists() || !indexDir.isDirectory()){ indexDir.mkdirs();}IndexWriter writer = new IndexWriter( FSDirectory.open(indexDir),newStandardAnalyzer(Version.LUCENE_30),true,IndexWriter.MaxFieldLength.UNLIMITED);//按照目录进行递归索引indexDirectory(writer,dataDir);int numIndexed = writer.numDocs();//对索引后的结果加以优化writer.optimize();writer.close();return numIndexed;}/*** 循环遍历目录下的所有.doc文件并进行索引* @param writer* @param dir* @throws IOException*/private static void indexDirectory(IndexWriter writer, File dir) throws IOException {File[] files = dir.listFiles();for (int i = 0; i < files.length; i++) {File f = files[i];if (f.isDirectory()) {indexDirectory(writer, f); // recurse} else if (f.getName().endsWith(".doc")) {indexFile(writer, f);}}}/*** 对单个doc文件进行索引* @param writer* @param f* @throws IOException*/private static void indexFile(IndexWriter writer, File f)throws IOException {if (f.isHidden() || !f.exists() || !f.canRead()) {return;}System.out.println("Indexing " + f.getCanonicalPath());Document doc = new Document();doc.add(new Field("content",new FileReader(f)));doc.add(new Field("filename",f.getName(),Field.Store.YES,Field.Index.ANALYZED));doc.add(new Field("path",f.getCanonicalPath(),Field.Store.YES, Field.Index.ANALYZED));writer.addDocument(doc);}}2)查询用类:/*** 对索引结果进行搜索* @author roy**/public class Searcher {private static String INDEX_DIR = "G:\\ROY的各种笔记\\索引"; //索引所在的路径private static String KEYWORD = "自己"; //关键词private static int TOP_NUM = 100; //显示前100条结果/*** 测试主函数* @param args* @throws Exception*/public static void main(String[] args) throws Exception{File indexDir = new File(INDEX_DIR);if (!indexDir.exists() || !indexDir.isDirectory()){throw new Exception(indexDir + "索引目录不存在!");}search(indexDir,KEYWORD); //调用search方法进行查询}/*** 索引查找方法* @param indexDir 索引所在的目录* @param q 查询的字符串* @throws Exception*/private static void search(File indexDir, String q) throws Exception {IndexSearcher is = newIndexSearcher(FSDirectory.open(indexDir),true); //read-onlyString field = "content";//创建查询解析器QueryParser parser = new QueryParser(Version.LUCENE_30, field, new StandardAnalyzer(Version.LUCENE_30));Query query = parser.parse(q);//创建结果收集器TopScoreDocCollector collector =TopScoreDocCollector.create(TOP_NUM ,false);//有变化的地方long start = new Date().getTime();// start timeis.search(query, collector);ScoreDoc[] hits = collector.topDocs().scoreDocs;System.out.println(hits.length);for (int i = 0; i < hits.length; i++) {Document doc = is.doc(hits[i].doc);//new method is.doc()System.out.println(doc.getField("filename")+" "+hits[i].toString()+" ");}long end = new Date().getTime();//end timeSystem.out.println("Found " + collector.getTotalHits() +" document(s) (in " + (end - start) +" milliseconds) that matched query '" +q + "':");}}3、分词器的选择分词器是一个搜索引擎的核心之一,好的分词器可以把关键字分解为更接近于用户的搜索目标的词汇。

Lucene3.0

Lucene3.0

分词原理建立索引和查询的过程中,都是以基本的语素项为单位的。

基本的语素项就是通过分词得到。

这个过程决定了索引单元金额最终的匹配过程。

分词在文本索引的建立过程和用户提交检索过程中都存在。

利用相同的分词器,把短语或者句子切分成相同的结果,才能保证检索过程顺利进行。

1、英文分词的原理基本的处理流程是:输入文本、词汇分割、词汇过滤(去除停留词)、词干提取(形态还原)、大写转为小写、结果输出。

2、中文分词原理中文分词比较复杂,并没有英文分词那么简单。

这主要是因为中文的词与词之间并不像英文中那样用空格来隔开。

主要的方法有三种:基于词典匹配的分词方法、基于语义理解的分词、基于词频统计的分词。

① 基于词典匹配的分词方法基于字典匹配的分词方法按照一定的匹配策略将输入的字符串与机器字典词条进行匹配。

如果在词典中找到当前字符串,则匹配成功输出识别的词汇。

按照匹配操作的扫描方向不同,字典匹配分词方法可以分为正向匹配和逆向匹配,以及结合了两者的双向匹配算法;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与词性标注相结合的方法。

几种常用的词典分词方法如下所示:● 正向最大匹配(由左到右的方向)。

● 逆向最大匹配(由右到左的方向)。

● 最少切分(是每一句中切除的词数最小)。

实际应用中上述各种方法经常组合使用,达到最好的效果,从而衍生出了结合正向最大匹配方法和逆向最大匹配算法的双向匹配分词法。

由于中分词最大的问题是歧义处理,结合中文语言自身的特点,经常采用逆向匹配的切分算法,处理的精度高于正向匹配,产生的切分歧义现象也较少。

真正实用的分词系统,都是把词典分词作为基础手段,结合各种语言的其他特征信息来提高切分的效果和准确度。

有的实用系统中将分词和词性标注结合起来,利用句法和词法分析对分词决策提高帮助,在词性标注过程中迭代处理,利用词性和语法信息对分词结果进行检验、调整。

Lucene全文检索学习笔记

Lucene全文检索学习笔记

全文索引介绍Lucene的作者:Lucene的贡献者Doug Cutting是一位资深全文索引/检索专家,曾经是V-Twin搜索引擎(Apple的Copland操作系统的成就之一)的主要开发者,后在Excite担任高级系统架构设计师,目前从事于一些INTERNET底层架构的研究。

他贡献出的Lucene的目标是为各种中小型应用程序加入全文检索功能。

原理lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。

在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。

因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。

一、搭建环境a)导包:1.IKAnalyzer3.2.0Stable.jar //中文分词器2.lucene-analyzers-3.0.1.jar //英文分词器3.lucene-core-3.0.1.jar //核心包4.lucene-highlighter-3.0.1.jar//关键字高亮显示5.lucene-memory-3.0.1.jar //缓存机制二、建立索引a)步骤:1.创建索引的javaBean类文件,如Article.java2.创建全文检索库,Directory directory = FSDirectory.open(newFile("./indexDir"));3.创建分词器,Analyzer analyzer = newStandardAnalyzer(Version.LUCENE_30);//在这里使用的是Lucene自带的分词器,也可以使用上面的IKAnalyzer中文分词4.创建IndexWriter对象,IndexWriter indexWriter = new IndexWriter(directory,analyzer,MaxFieldLength.UNLIMITED);5.创建Document对象,Document document = new Document();6.将Article对象转换为Document对象,Field idField = new Field("id",article.getId().toString(), Store.YES, Index.NOT_ANALYZED);7.将Field添加到Document中,document.add(idField);8.将Document对象写入到索引库中,indexWriter.addDocument(document);9.最后,切记关闭IndexWriter对象,否则会产生一个锁文件,导致下面无法执行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Lucene3.0之查询处理(1):原理1、查询的三种方式①顺序查询:简单,但查询效率低②索引查询:快速,需要基础索引结构支撑2、理论模型①布尔模型:基于集合论和布尔代数的一种简单检索模型②向量模型:查询串和文档之间分配不同的权值,权值大小放映了文档库中的文档与用户查询串的相关度。

查询得到的结果文档按照权值计算相关度有关排序,所以向量模型得到的匹配文档可以是全部精确匹配,也可以是部分匹配查询串。

3、查询流程用户查询请求输入->查询词频->查询词频出现->查询词格式化->文本库索引匹配->相似度和排序计算->结果排重与生成。

4、Lucence3.0查询概述1、主要利用查询工具IndexSearcher类这是检索的主要控制和工具,也是所有搜索操作的入口。

其构造方法主要有:IndexSearcher(Directory path)IndexSearcher(Directory path, boolean readOnly)IndexSearcher(IndexReader r)IndexSearcher(IndexReader reader, IndexReader[] subReaders, int[] docStarts)这里推荐主要使用第1个和第2个构造方法。

2、其它相关的类①Query:抽象类,必须通过一系列子类来表述检索的具体需求。

②QueryParser:查询分析器。

处理用户输入的查询条件。

把用户输入的非格式化检索词转化成后台检索可以理解的Query对象查询最基本的结果返回方式是通过Hits对象来提供。

Hits提供了检索查询结果的缓冲,为结果的展示和返回提供支持。

Hits中的结果集已经按照相关性进行了排序,前面的文档结果表明与查询词更为相似。

Lucene3.0之查询(2):查询类型1、查询Query对象Lucnce查询主要有两种方式。

一是通过Query子类构造函数方法生成子类。

这种方法最大的好处是非常直观,可以根据自己的功能目标挑选合适的子类来够着具体的Query对象。

另一种查询方式是通过QueryParse动态构造查询对象。

这种方法使用了parse方法,具体构造的对象类型需要根据查询词的内容来确定。

除了少数特殊查询,几乎所有的查询检索都可以通过QueryParser来代替特定子类的构造函数来查询对象生成功能。

2、最小项查询TermQuery适合关键字查询文档,大小写敏感。

①Term term = new Term(“content”, “星期一”);TermQueryquery = new TermQuery(term);②String str = “星期一”;Analyzer analyzer = new Analyzer();QueryParser parser = new QueryParser(“content”, analyzer);Query query = parser.parse(str);3、区域范围查询RangeQuery在年龄、日期、分数、数量等情况下经常会使用到。

通常的模式使用起始值和终止值来确定区间。

有点类似SQL语句中的between…and…语句。

生成RangeQuery的实例需要两个对应的Term对象分别描述起始点和终止点。

另外还要有一个标志参数,用来表明是否包含区间范围的边界。

如果标志参数为true,表明检索查询匹配时需要包含边界,否则为不包含边界。

①Term termStart = new Term(“weight”, ”40”);Term termEnd = new Term(“weight”, “50”);TermRangeQuery query = new TermRangeQuery("numval",lowerTerm,upperTerm,true,true);②String str = “{40 TO 50}”;Analyzer analyzer = new Analyzer();QueryParser parser = new QueryParser(“content”, analyzer);Query query = parser.parse(str);4、逻辑组合搜索BooleanQuery①Term term1 = new Term(“content”, “星期一”);Term term2 = new Term(“content”, “五月一日”);TermQuery query1 = new TermQuery(term1);TermQuery query2 = new TermQuery(term2);BooleanQuery query = new BooleanQuery();Query.add(query1.BooleanClause.Occur.MUST);Query.add(query2.BooleanClause.Occur.MUST);AND查询:MUST+MUST;NO查询:MUST+MUST_NOT或者SHOULD+MUST_NOT;OR 查询:SHOULD+SHOULD;②String str = ”(星期一AND五月一日)”Analyzer analyzer = new Analyzer();QueryParser parser = new QueryParser(“content”, analyzer);Query query = parser.parse(str);5、字串前缀查询RefixQuery①使用PrefixQuery构造前缀查询前缀查询的直接构造方法是使用Term构造一个最小项对象,同时把它作为前缀的生成参数。

构造的查询对象提交检索查询,得到的结果以Term项内的文本值为开头字符的所有文章。

Term term = new Term(“content”, “五月一日”);PrefixQuery query = new PrefixQuery(term);②String str = “(五月一日)”;Analyzer analyzer = new Analyzer();QueryParser parser = new QueryParser(“content”, analyzer);Query query = parser.parse(str);6、短语搜索PhraseQuery①PhraseQuery构造短语查询Term term1 = new Term(“content”, “星期”);Term term2 = new Term(“content”, “一”);PhraseQuery query = new PhraseQuery();query.add(term1);query.add(term2);query.setSlop(1);PhraseQuery和Boolean的区别:PhraseQuery对象的查询结果符合关键词的添加次序。

BooleanQuery的与检索查询结果范围更大,检索项次序相反的文档也会检索到。

严格的检索词次序匹配会限制使用范围。

为了能找到最相近的结果,可以使用setSlop方法,指定小于编辑距离的匹配文档也作为结果出现。

②QueryParser构造短语查询用户输入的单个检索项的查询词会通过QueryParser的Parse方法生成TermQuery对象,带空格的多个检索项会生成BooleanQuery对象的与检索。

如果要生成PhraseQuery对象,需要给查询间加上双引号。

String str = “\”星期一\””;Analyzer analyzer = new Analyzer();QueryParser parser = new QueryParser(“content”, analyzer);Query query = parser.parse(str);7、模糊查询FuzzyQuery这种模糊查询搜索是按照检索文本的形似度进行判断的。

两个检索器或者字符串的相似是通过编辑距离来判定的。

这种编辑距离实际上是表明两个不同的字符串需要经过多少次编辑和变换才能变为对方。

通常的编辑行为包括了增加一个检索项,删除一个检索项,修改一个检索项,与普通的字符串匹配函数不同,模糊搜索里的编辑距离是以索引项为单位的。

①FuzzyQuery()Term term = new Term(“content”, “星期”);FuzzyQuery query = new FuzzyQuery(term);②QueryParser:查询词后携带“~0.1f”格式的限定。

整个查询词不需要专门使用双引号。

String str = “星期一~0.1f”;8、通配符查询WildcardQuery?:1个特定字符;*:0个或者多个待定字符。

①Term term = new Term(“content”, “星期*”);WildcardQuery query = new WildcardQuery(term);②String str = “0*1”;9、位置跨度查询SpanQuery①SpanTermQuerySpanTermQuery携带了位置信息的Term对象查询类,单独使用时输出地结果与TermQuery相同。

但是它携带的位置信息可以为其它复杂的SpanQuery提供支持,是跨度检索的基础类。

也可以为后续的自定义排序规则提供位置信息,或者用来特殊显示相关结果。

②SpanFirstQuerySpanFirstQuery用来指定查询域中前面指定数量索引项的范围内进行检索,提高查询检索效率。

如果匹配的检索项在指定范围之外,查询中不会返回该文档作为结果。

Term t = new Term(“content”, str);SpanTermQuery query = new SpanTermQuery(t);SpanFirstQuery firstquery = new SpanFirstQuery(query, 2);③SpanNearQuerySpanNearQuery用来指定不同查询检索项在文本中的间隔距离,如果间隔太久,以致超出了参数指定的距离。

即使所有检索引都存在,也不能作为结果输出。

查询过程需要生成多个Term对象,利用每个Term对象分别构造SpanTermQuery对象并形成数组。

Term t1 = new Term(“content”, “星期一”);Term t2 = new Term(“content”, “星期二”);Term t3 = new Term(“content”, “星期三”);SpanTermQuery query1 = new SpanTermQuery(t1);SpanTermQuery query2 = new SpanTermQuery(t2);SpanTermQuery query3 = new SpanTermQuery(t3);SpanQuery[] queryarray = new SpanQuery[]{query1, query2, query3};SpanNearQuery nearQUery = new SpanNearQuery(queryarray, 1, true);④SpanNotQuerySpanNotQuery用来指定查询中,某两个查询对内容会不会发生重叠,如果特定索引项落入到查询的跨度范围内,就把该文档以结果集中排除使用SpanNearQuery相同。

相关文档
最新文档