`
杨振华
  • 浏览: 9546 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Lucene2--索引的增删改查

阅读更多
1.全文检索系统的结构

2.Lucene倒排索引原理
假设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.
经过分词处理后
    文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
    文章2的所有关键词为:[he] [live] [shanghai]
加上“出现频率”和“出现位置”信息后,我们的索引结构为:

3.索引的增删改查
核心索引类:
public class IndexWriter
org.apache.lucene.index.IndexWriter
public abstract class Directory
org.apache.lucene.store.Directory
public abstract class Analyzer
org.apache.lucene.analysis.Analyzer
public final class Document
org.apache.lucene.document.Document
public final class Field
org.apache.lucene.document.Field 示例代码:

package cn.yang;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
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.apache.lucene.util.Version;

public class IndexUtil {
	//准备数据
	private String[] ids = { "1", "2", "3", "4", "5", "6" };
	private String[] emails = { "aa@yang.org", "bb@sina.org", "cc@aa.org", "dd@qq.org",
			"ee@yahoo.org", "ff@yi.org" };
	private String[] content = { "welcom to visited", "hello boy",
			"my name is yang", "liu meigui is a dog", "haha fuck",
			"i like fuck liu" };
	private int[] attaches = { 2, 4, 4, 5, 6, 7 };
	private String[] names = { "zhangsan", "lisi", "yuhan", "john", "dav",
			"liu" };
	private Date[] dates = null;
	
	//加权信息
	private Map<String,Float> scores = new HashMap<String,Float>();

	private Directory directory = null;
	
	//因IndexReader打开耗费资源 故使用静态的
	private static IndexReader reader = null;
	
	//初始化日期
	public void setDates(){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyymmdd");
		dates = new Date[ids.length];
		try {
			dates[0] = sdf.parse("2014-03-20");
			dates[1] = sdf.parse("2012-03-22");
			dates[2] = sdf.parse("2013-03-21");
			dates[3] = sdf.parse("2011-03-20");
			dates[4] = sdf.parse("2014-03-23");
			dates[5] = sdf.parse("2014-03-24");
		} catch (ParseException e) {			
			e.printStackTrace();
		}
	}
    
	//构造函数内舒适化加权信息及directory、reader
	public IndexUtil() {
		try {
			scores.put("yang.org", 2.0f);
			scores.put("sina.org", 2.0f);
			directory = FSDirectory.open(new File("d:/lucene/indextest"));
			//false设置reder不为只读
			reader = IndexReader.open(directory,false);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//得到IndexSearcher
	public IndexSearcher getSearcher(){
		//实时更新单例reder
		try {
			if(null == reader){		
				//false设置reder不为只读
				reader = IndexReader.open(directory,false);
			} else {
				IndexReader tr = IndexReader.openIfChanged(reader);
				if (null != tr) 
				reader.close();	
				reader=tr;
			}
			return new IndexSearcher(reader);
		}catch (Exception e) {			
			e.printStackTrace();
		} 
		return null;
		
		
		
	}

	// 创建索引步骤:创建Directory;创建IndexWriter;创建Document并add Field;将Document加入IndexWriter
	public void index() {
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			Document doc = null;
			for (int i = 0; i < ids.length; i++) {
				doc = new Document();
				// Field.Store.YES或NO (存储域选项)
				// YES表示把这个域即field中的内容完全存储到索引文件中,方便进行文本的还原
				// NO表示把这个域中的内容不存储到索引文件中,但是可以被索引,但是内容无法完全还原

				// Field.Index (索引域选项)
				// Index.ANALYZED:进行分词和索引,适用于标题内容等
				// Index.NOT_ANALYZED:进行索引,但是不进行分词,如身份证号,姓名,ID等适用于精确搜索
				// Index.ANALYZED_NOT_NORMS:即进行分词但不存储norms信息,信息中包括创建索引的时间和权值等信息,影响评分排序的信息
				// Index.NOT_ANALYZED_NOT_NORMS:不分词不存储
				// Index.NO:不进行索引
				doc.add(new Field("id", ids[i], Field.Store.YES,
						Field.Index.NOT_ANALYZED_NO_NORMS));
				doc.add(new Field("email", emails[i], Field.Store.YES,
						Field.Index.ANALYZED));
				doc.add(new Field("content", content[i], Field.Store.NO,
						Field.Index.ANALYZED));
				doc.add(new Field("name", names[i], Field.Store.YES,
						Field.Index.NOT_ANALYZED_NO_NORMS));
				//为数字加索引
				doc.add(new NumericField("attaches", Field.Store.YES,true).setIntValue(attaches[i]));
				//为日期字段加索引
				doc.add(new NumericField("date", Field.Store.YES,true).setLongValue(dates[i].getTime()));
					
				//加权信息
				String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
				if(scores.containsKey(et)){
					doc.setBoost(scores.get(et));			
				}else{
					doc.setBoost(0.5f);	
				}
						
				writer.addDocument(doc);
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (writer != null)
				try {
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}
	public void seach01(){
		try {	
			// 创建IndexReader
			IndexReader reader = IndexReader.open(directory);
			// 根据IndexWriter创建IndexSearcher
			IndexSearcher seacher = new IndexSearcher(reader);
			// 创建搜索的Query
			TermQuery query = new TermQuery(new Term("content","like"));
			// 根据seacher搜索并返回TopDocs
			TopDocs tds = seacher.search(query, 10);			
			// 根据TopDocs获取ScoreDoc
			ScoreDoc[] sds = tds.scoreDocs;
			for(ScoreDoc sd: sds){
				// 根据seacher和ScoreDoc对象获取具体的Dcument对象
				Document d = seacher.doc(sd.doc);
				// 根据Dcument对象获取需要的值
				System.out.println("id:"+d.get("id"));
				System.out.println("name:"+d.get("name"));
				System.out.println("email:"+d.get("email"));
				System.out.println("attach:"+d.get("attaches"));
				System.out.println("date:"+d.get("date"));
			}	
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void seach02(){
		try {	
		
			// 调用方法getSearcher()取得IndexSearcher
			IndexSearcher seacher = getSearcher();
			// 创建搜索的Query
			TermQuery query = new TermQuery(new Term("content","like"));
			// 根据seacher搜索并返回TopDocs
			TopDocs tds = seacher.search(query, 10);			
			// 根据TopDocs获取ScoreDoc
			ScoreDoc[] sds = tds.scoreDocs;
			for(ScoreDoc sd: sds){
				// 根据seacher和ScoreDoc对象获取具体的Dcument对象
				Document d = seacher.doc(sd.doc);
				// 根据Dcument对象获取需要的值
				System.out.println("id:"+d.get("id"));
				System.out.println("name:"+d.get("name"));
				System.out.println("email:"+d.get("email"));
				System.out.println("attach:"+d.get("attaches"));
				System.out.println("date:"+d.get("date"));
			}	
			seacher.close();
		
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//查询
	public void query(){
		IndexReader reader = null;
		try {
			//获得文档数量
			reader = IndexReader.open(directory);
			System.out.println("numDocs:"+reader.numDocs());
			System.out.println("maxDocs:"+reader.maxDoc() );
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if (reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}
	//删除索引   通过writer删除文档
	public void delete(){
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			//删除id1的文档 参数还可以是一个query或一个term(精确查找的值)
			//删除的文档并不会被完全删除,而是存储在一个单独类似回收站文件,可进行恢复
			writer.deleteDocuments(new Term("id","1"));
			//清空回收站 不可恢复
			writer.forceMergeDeletes();
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			if (writer != null)
				try {
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
		
	}
	
	//删除索引   通过reader删除文档
	public void delete02(){		
		try {
			reader.deleteDocuments(new Term("id","1"));
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			
		}
		
	}
	//恢复删除的文档
	public void undelete(){
		IndexReader reader = null;
		try {
			reader = IndexReader.open(directory,false);
			//恢復時必須把IndexReader的只读属性設置為false
			reader.undeleteAll();
			
			System.out.println("numDocs:"+reader.numDocs());
			System.out.println("maxDocs:"+reader.maxDoc() );
			System.out.println("deleteDocs:"+reader.numDeletedDocs() );
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			if (reader != null)
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	//优化合并
	public void merge(){
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			//将索引合并为两段,这两段中被删除的数据会被清空
			writer.forceMerge(2);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			if (writer != null)
				try {
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}
	//更新操作
	public void update(){
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			//lucene并不提供更新,更新为先删除后添加
			Document doc = new Document();
			doc.add(new Field("id", "11", Field.Store.YES,
					Field.Index.NOT_ANALYZED_NO_NORMS));
			doc.add(new Field("email", emails[0], Field.Store.YES,
					Field.Index.ANALYZED));
			doc.add(new Field("content", content[0], Field.Store.NO,
					Field.Index.ANALYZED));
			doc.add(new Field("name", names[0], Field.Store.YES,
					Field.Index.NOT_ANALYZED_NO_NORMS));
			writer.updateDocument(new Term("id","1"), doc);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			if (writer != null)
				try {
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}

}

package cn.yang;

import org.junit.Test;

public class TestIndex {
	
	@Test
	public void testIndex(){
		IndexUtil iu = new IndexUtil();
		iu.index();
		
	}
	@Test
	public void testQuery(){
		IndexUtil iu = new IndexUtil();
		iu.query();
		
	}
	@Test
	public void testDelete(){
		IndexUtil iu = new IndexUtil();
		iu.delete();
	}
	@Test
	public void testunDelete(){
		IndexUtil iu = new IndexUtil();
		iu.undelete();
	}
	
	@Test
	public void testSerch01(){
		IndexUtil iu = new IndexUtil();
		iu.seach01();
	}
	
	@Test
	public void testSerch02(){
		IndexUtil iu = new IndexUtil();
		//iu.seach02();
		for(int i=0;i<5;i++){
			iu.seach02();
			System.out.println("----------");
			iu.seach02();
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}


4.域选项介绍:
Field.Index 表示Field的索引方式
NO 表示该Field不需要索引,也就是用户不需要去查找该Field的值
NO_NORMS 表示对该Field进行索引,但是不使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗
TOKENIZED 表示该Field先被分词再索引
UN_TOKENIZED 像链接地址URL、文件系统路径信息、时间日期、人名、居民身份证、电话号码等等通常将被索引并且完整的存储在索引中,但一般不需要切分词

Field.Store 表示Field的存储方式
COMPRESS压缩存储
NO 原文不存储在索引文件中,搜索结果命中后,再根据其他附加属性如文件的Path,数据库的主键等,重新连接打开原文,适合原文内容较大的情况。
YES索引文件本来只存储索引数据, 此设计将原文内容直接也存储在索引文件中,如文档的标题。
5.IndexReader和IndexWriter的生命周期问题
IndexReader耗资源,做成单例
IndexReader在工作时IndexWriter重建或者更新了索引,假如IndexReader为单例模式,不 
能实时查询到IndexWriter的更新
解决方法:IndexReader.openIfChanged(reader);
IndexWriter在项目中有可能只存在一个,故操作后要进行commit
  • 大小: 37.5 KB
  • 大小: 5.7 KB
分享到:
评论

相关推荐

    lucene3.5的创建和增删改查

    《Lucene 3.5:创建、增删改查详解》 Lucene 是一个高性能、全文本搜索库,被广泛应用于各种搜索引擎的开发。在3.5版本中,Lucene 提供了强大的文本分析和索引功能,以及对文档的高效检索。本文将详细介绍如何在...

    lucene增删改查小demo

    这个“lucene增删改查小demo”涵盖了 Lucene 搜索库的基础操作,通过 IndexWriter 进行索引管理,使用 QueryParser 构建查询,IndexSearcher 执行查询,并通过 Document 实现数据的读写。掌握这些基本操作后,你可以...

    Lucene3.0增删改查和关键字高亮实例

    在这个“Lucene3.0增删改查和关键字高亮实例”项目中,我们将深入理解如何利用Lucene 3.0版本进行索引构建、文档的增删改查操作,并学习关键字高亮显示的实现方法。 首先,我们要了解**创建索引**的基本流程。在...

    Lucene.net增删改查示例,使用多索引和盘古分词等方法,并实现分页查询

    这是一个Lucene.net的多索引示例,以数据库的动态数据为数据源,每个表对应一个索引,使用了盘古分词方法,适用于中文的分词,并且实现了增删改查的所有功能。 同时,在查询索引时,适用了分页方法,可直接引用到...

    lucene5.3.1增删改查

    **Lucene 5.3.1 增删改查详解** Lucene 是一个高性能、全文本搜索引擎库,由 Apache 软件基金会开发。它提供了丰富的搜索功能,包括分词、评分、高亮显示等,是Java平台上的首选文本搜索解决方案。在Lucene 5.3.1...

    lucene事例(包含基本增删改查、中文词分器、高亮显示等)

    在本示例中,我们将探讨如何使用Lucene进行基本的增删改查操作,并且了解如何处理中文文档以及利用Luke工具进行索引分析,以及实现搜索结果的高亮显示。 首先,让我们深入理解Lucene的基础概念。Lucene的核心是建立...

    lucene增删改查+IKAnalyzer

    Lucene的核心功能包括索引和搜索。索引过程是将非结构化的文本数据转换为倒排索引,使得搜索操作能够快速定位到相关文档。搜索阶段,Lucene会根据用户输入的查询字符串,通过倒排索引来匹配最相关的文档。 Lucene的...

    lucene全文检索实例二(实现对10万条数据检索文件的增删改查操作)

    在这个实例中,开发者将展示如何在含有10万条数据的环境中实现文件的全文检索,并且包括增、删、改、查这四种基本操作。Lucene是一个强大的文本分析和搜索框架,它允许开发者构建高效且复杂的搜索功能。 描述中的...

    solr的增删改查和高亮以及分组

    本文将深入探讨Solr 3.6版本中的核心功能:增删改查(CRUD)操作,高亮显示,以及分组查询。 ### 1. Solr的增删改查操作 #### 1.1 创建(Create) 在Solr中,创建文档通常涉及到定义一个XML或JSON格式的文档结构...

    Lucene-WEB-search-program.zip_lucene java web_lucene web_lucene

    Lucene提供了增删改查的API,确保索引始终与数据同步。 4. **搜索实现**:用户提交查询后,应用将查询字符串转换为Query对象,然后使用IndexSearcher进行查询。查询结果会返回一个ScoreDoc数组,表示每个匹配文档的...

    【JEST连接ES(6.0)进行增删改查】

    本文将详细讲解如何在JDK 1.8环境下,利用JEST 5.0以上版本与ES 6.0以上版本进行增删改查操作。 首先,确保你已经正确安装并配置了JDK 1.8。JDK是Java开发工具包,是运行Java应用程序的基础。在安装JDK后,你需要...

    1.3、索引库使用的增删改查,以及数据库的连接导入1

    【数据库索引库的增删改查】 在数据库管理中,索引库是提升查询效率的关键,特别是对于大型数据集,它可以显著加快数据检索的速度。本文主要探讨索引库的常用操作,包括增、删、改、查以及数据库的连接与导入。 1....

    lucene-project.rar

    索引库的维护包括对已索引数据的增、删、改、查。在Lucene中,如果数据有变化,我们需要更新索引以保持与数据同步。`IndexWriter`提供了这些功能,如添加新文档、删除文档、更新现有文档等。同时,索引优化也是维护...

    关于elasticsearch5.3.0基础增删改查实例文件

    **Elasticsearch 5.3.0 基础增删改查实例解析** Elasticsearch 是一个基于 Lucene 的分布式、RESTful 风格的搜索和数据分析引擎,广泛应用于日志分析、实时监控、数据挖掘等领域。版本 5.3.0 是其历史中的一个重要...

    es客户端工具,便捷操作es全文检索工具的增删改查

    本文将深入探讨如何使用客户端工具来便捷地进行ES的增删改查操作,以及这些工具在全文检索和搜索引擎中的应用。 ### 一、Elasticsearch概述 Elasticsearch基于Lucene库构建,提供了分布式、实时、容错的全文检索...

    springboot集合elasticsearch demo(内含增删改查)

    这个Demo项目提供了SpringBoot与Elasticsearch的整合示例,包括了基础的增删改查操作,帮助开发者快速理解如何在实际应用中使用Elasticsearch。 首先,SpringBoot是Spring框架的一个轻量级版本,它简化了新Spring...

    lucene创建修改删除组合条件查询

    首先,**创建索引**是使用Lucene的第一步。创建索引涉及到读取数据源(如文件或数据库),解析内容,然后将这些内容转换为Lucene可以理解的文档结构。每个文档由一个或多个字段组成,每个字段都有其特定的类型(如...

    博客系统(搜索利用Lucene)

    博客类别信息管理:增删改查,分页 评论管理: 评论信息管理:删查,分页 个人信息管理: 修改个人信息:图片上传和利用百度编辑器完成; 系统管理: 修改密码: 刷新系统缓存: 安全退出: 项目前台功能...

    Lucene与SQL对比学习

    - **SQL**:SQL语言提供了强大的数据增删改查功能,如`SqlExecute`函数所示,通过SQL语句实现对数据库的操作,具有事务处理和并发控制等高级特性。 - **Lucene**:Lucene的添加操作如`InsertProductLucene`函数所...

    全文搜索引擎lucene入门

    同时,Lucene提供了对文档的增删改查操作。 ### 三、Lucene入门实践 1. **安装和配置**:首先,你需要在项目中添加Lucene的依赖,可以通过Maven或Gradle等构建工具来实现。 2. **创建索引**: - 创建`Directory`...

Global site tag (gtag.js) - Google Analytics