Lucene索引创建方法和步骤

在全文索引工具中,都是由这样的三部分组成

1.索引部分

2.分词部分

3.搜索部分

----------------------------------

索引创建域选项

----------------------------------

Field.Store.YES或者NO(存储域选项)

YES:表示会把这个域中的内容完全存储到文件中,方便进行还原[对于主键,标题可以是这种方式存储]

NO:表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原(doc.get())[对于内容而言,没有必要进行存储,可以设置为No]

Field.index(索引选项)

Index.ANALYZED:进行分词和索引,适用于标题,内容等

Index.NOT_ANALYZED:进行索引,但不进行分词,比如身份证号,姓名,ID等,使用于精确搜索

Index.ANALYZED_NOT_NORMS:进行分词但是不存储norms信息,这个norms中包含了创建索引的时间和权值(排序)等信息

Index.NOT_ANALYZED_NOT_NORMS:即不进行分词也不存储norms信息

Index.NO:不进行索引

最佳实践

NOT_ANALYZED_NOT_NORMS  Store.YES     标识符(主键,文件名),电话号码,身份证号,姓名,日期

ANALYZED                                Store.YES     文档标题和摘要

ANALYZED                                Store.NO     文档正文

NO                                            Store.YES    文档类型,数据库主键(不进行索引)

NOT_ANALYZED                       Store.NO      隐藏关键字

索引文件结构剖析

.fnm保存着域字段的信息

.fdt和.fdx保存着store=yes的数据

.frq保存着哪些相同的单词出现多少次(可用作排序和评级)

.nrm专门用来保持一些评级信息

.tii和.tis保存着索引里面的所有信息

文档和域的概念

文档相当于表中的每一条记录,域相当于表中的每一个字段

----------------------------------

索引的删除与更新

----------------------------------

1.删除

writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));

// 参数是一个选项,可以是一个query,也可以是一个term,term是一个精确查找的值

// 此时删除的文档并不会被完全删除,而是存储在一个回收站中,可以恢复

writer.deleteDocuments(new Term("id", "1"));

2.恢复删除

// 使用indexreader恢复

// 将readeronly=false

IndexReader reader = IndexReader.open(directory, false);

reader.undeleteAll();

reader.close();

3.强制删除(清空回收站)

writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));

// 强制删除数据,清空回收站

// Lucene3.5之前是optimize()方法进行处理,但此方法消耗大量内存已经被弃用

writer.forceMergeDeletes();

4.优化和合并

writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));

// 添加了多次索引,可以设置允许的最大段索引,会将索引合并为两段,这两段中的被删除的数据会被情空

// 特别注意:此次不建议使用,会消耗大量的开销,Lucene会根据情况自动优化

writer.forceMerge(2);

5.更新索引

writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));

/*

* Lucene并没有提供更新的操作,这里的更新是两个操作的合并 先删除之后再添加

*/

Document doc = new Document();

// 先将文档id=1的索引删除,再添加一个新的文档索引

// 先删除再代替的工作

writer.updateDocument(new Term("id", "1"), doc);

--------------------------------------------------

lucene索引_加权操作

--------------------------------------------------

通过Map<String, Float> scores = new HashMap<String, Float>();方式进行设置

假设对特定邮箱进行评级

/*

*
document.setBoost(float) 设置评级

*/

String et = emails[i].substring(emails[i].lastIndexOf("@") + 1);

//System.out.println(et);

if (scores.containsKey(et)) {

document.setBoost(scores.get(et));

} else {

document.setBoost(0.5f);

}

--------------------------------------------------

对日期和数字进行索引

--------------------------------------------------

private int[] attachs = { 2, 3, 1, 4, 5, 5 };

private Date[] dates = null;

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

dates = new Date[ids.length];

dates[0] = sdf.parse("2015-1-1");

dates[1] = sdf.parse("2015-2-1");

dates[2] = sdf.parse("2015-3-1");

dates[3] = sdf.parse("2015-4-1");

dates[4] = sdf.parse("2015-5-1");

dates[5] = sdf.parse("2015-6-1");

// 为数字添加索引

document.add(new NumericField("attach", Field.Store.YES, true).setIntValue(attachs[i]));

// 给日期添加索引

document.add(new NumericField("date", Field.Store.YES, true).setLongValue(dates[i].getTime()));

1.创建索引代码

 * 一.建立索引
	 */
	public void index() {

		IndexWriter writer = null;
		try {
			// 1.创建Directory(索引位置)
			// 创建内存的索引
			// Directory directory = new RAMDirectory();
			// 创建自定义的索引位置
			Directory directory = FSDirectory
					.open(new File(
							"F:/BaiduYunDownload/Cache/lucune/LuceneExamples/indexdata"));
			// 2.创建IndexWriter(写入索引)
			IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35,
					new StandardAnalyzer(Version.LUCENE_35));// 参数2Analyzer表示创建的分词器
			writer = new IndexWriter(directory, conf);
			// 3.创建Document对象
			Document document = null;
			// 4.为Document添加Field(相当于添加些属性)
			File fs = new File(
					"F:/BaiduYunDownload/Cache/lucune/LuceneExamples/testdata");
			// 遍历所有文件
			for (File f : fs.listFiles()) {
				document = new Document();
				// 将内容添加成索引
				document.add(new Field("content", new FileReader(f)));
				// 添加文件的名字 第三个参数将文件的名字存储到索引中 第四个参数是否进行分词
				document.add(new Field("fileName", f.getName(),
						Field.Store.YES, Field.Index.NOT_ANALYZED));
				// 添加文件的路径
				document.add(new Field("path", f.getAbsolutePath(),
						Field.Store.YES, Field.Index.NOT_ANALYZED));
				// 5.通过IndexWriter添加文档到索引中

				writer.addDocument(document);
			}

		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

2.对索引进行的增删改更新操作

/*
 * 用作专门创建索引的工具
 */
public class IndexUtil {
	/*
	 * 假设6个文档
	 */
	private String[] ids = { "1", "2", "3", "4", "5", "6" };
	private String[] emails = { "[email protected]", "[email protected]", "[email protected]",
			"[email protected]", "[email protected]", "[email protected]" };
	private String[] contents = { "hello boy,i like pingpang", "like boy",
			"xx bye i like swim", "hehe, i like basketball",
			"dd fsfs, i like movie", "hello xxx,i like game" };
	private int[] attachs = { 2, 3, 1, 4, 5, 5 };
	private Date[] dates = null;
	private String[] names = { "lili", "wangwu", "lisi", "jack", "tom", "mark" };
	// 设置加权map
	private Map<String, Float> scores = new HashMap<String, Float>();

	/*
	 * 创建索引
	 */
	private Directory directory = null;

	public IndexUtil() throws Exception {
		// 创建日期索引时,给日期赋值
		createDate();
		// 给Emails加权处理
		scores.put("sina", 2.0f);
		scores.put("google", 1.5f);

		directory = FSDirectory.open(new File(
				"F:/BaiduYunDownload/Cache/lucune/Code/code01/indexdata"));
	}

	/*
	 * 给日期属性初始化
	 */
	private void createDate() throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		dates = new Date[ids.length];
		dates[0] = sdf.parse("2015-1-1");
		dates[1] = sdf.parse("2015-2-1");
		dates[2] = sdf.parse("2015-3-1");
		dates[3] = sdf.parse("2015-4-1");
		dates[4] = sdf.parse("2015-5-1");
		dates[5] = sdf.parse("2015-6-1");

	}

	public void index() {
		IndexWriter writer = null;
		try {

			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			writer.deleteAll();
			// 创建documents
			Document document = null;
			for (int i = 0; i < ids.length; i++) {
				document = new Document();
				document.add(new Field("id", ids[i], Field.Store.YES,
						Field.Index.NOT_ANALYZED_NO_NORMS));
				document.add(new Field("email", emails[i], Field.Store.YES,
						Field.Index.NOT_ANALYZED)); // 不分词
				document.add(new Field("content", contents[i], Field.Store.NO,
						Field.Index.ANALYZED));
				document.add(new Field("name", names[i], Field.Store.YES,
						Field.Index.NOT_ANALYZED));
				// 为数字添加索引
				document.add(new NumericField("attach", Field.Store.YES, true)
						.setIntValue(attachs[i]));
				// 给日期添加索引
				document.add(new NumericField("date", Field.Store.YES, true)
						.setLongValue(dates[i].getTime()));
				/*
				 * document.setBoost(float) 设置评级
				 */
				String et = emails[i].substring(emails[i].lastIndexOf("@") + 1);
				// System.out.println(et);
				if (scores.containsKey(et)) {
					document.setBoost(scores.get(et));
				} else {
					document.setBoost(0.5f);
				}

				writer.addDocument(document);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

	}

	/*
	 * 强制优化索引(forceMerge()将所有索引都重新优化一遍)
	 */
	public void forceMerge() {
		IndexWriter writer = null;

		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			// 强制删除数据,清空回收站
			// Lucene3.5之前是optimize()方法进行处理,但此方法消耗大量内存已经被弃用
			writer.forceMergeDeletes();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

	/*
	 * 手动进行Merge优化
	 */
	public void merge() {
		IndexWriter writer = null;

		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			// 添加了多次索引,可以设置允许的最大段索引,会将索引合并为两段,这两段中的被删除的数据会被情空
			// 特别注意:此次不建议使用,会消耗大量的开销,Lucene会根据情况自动优化
			writer.forceMerge(2);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

	/*
	 * 恢复索引文件
	 */
	public void undelete() throws Exception {
		// 使用indexreader恢复
		// 将readeronly=false
		IndexReader reader = IndexReader.open(directory, false);
		reader.undeleteAll();
		reader.close();
	}

	/*
	 * 删除索引文件
	 */
	public void deleteIndex() {
		IndexWriter writer = null;

		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			// 参数是一个选项,可以是一个query,也可以是一个term,term是一个精确查找的值
			// 此时删除的文档并不会被完全删除,而是存储在一个回收站中,可以恢复
			writer.deleteDocuments(new Term("id", "1"));
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException 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();
			// 先将文档id=1的索引删除,再添加一个新的文档索引
			// 先删除再代替的工作
			writer.updateDocument(new Term("id", "1"), doc);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
					writer = null;
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

	/*
	 * 查询
	 */
	public void Query() throws Exception {
		IndexReader reader = IndexReader.open(directory);
		// 通过reader可以有效获取文档的数量
		System.out.println("本索引存储的文档数:" + reader.numDocs());
		System.out.println("总文档数(包括回收站):" + reader.maxDoc());
	}

	/*
	 * search
	 */
	public void Search() {
		try {
			IndexReader reader = IndexReader.open(directory);
			IndexSearcher search = new IndexSearcher(reader);
			// 精确搜索
			TermQuery query = new TermQuery(new Term("content", "like"));
			TopDocs tds = search.search(query, 10);
			for (ScoreDoc sd : tds.scoreDocs) {
				Document doc = search.doc(sd.doc);
				System.out.println(sd.doc + doc.get("name") + "["
						+ doc.get("email") + "," + doc.get("id") + ","
						+ doc.get("attach") + "," + doc.get("date") + "]");
			}
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}
时间: 2024-08-04 21:28:15

Lucene索引创建方法和步骤的相关文章

Lucene索引创建过程

一,Lucene建索引API 二,创建IndexWriter 三,创建Document 四,添加Document 1  Lucene使用场景 2  重要的几个基础类 2.1  DocumentsWriterPerThreadPool 2.2 ThreadState 2.3  DocumentsWriterPerThread 2.4  DocumentsWriterFlushControl 2.5  FlushPolicy 3  docWriter.updateDocument 4  docWri

lucene 索引创建步骤

一.步骤: 1.存储位置:1)文件: Directory dir= FSDirectory.open(new File("D:\\LuceneIndex")); 2)内存: new RAMDirectory(FSDirectory.getDirectory(file));//不建议,只会把一些搜索相关的信息放入到内存,不是全部的索引文件 2.分词器: Analyzer analyzer=new IKAnalyzer();//这个是中文分词器,并不是lucene自带的(StandardA

守护进程的创建方法与步骤

守护进程是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进程,Linux的大多服务器就是用守护进程实现的. 守护进程的创建步骤: 1.使进程在后台运行(创建子进程,父进程退出) if((pid=fork())>0) exit(0); else if (pid<0) { perror("fail to fork"); exit(-1); } 2.脱离控制终端,登录会话和进程组(创建新会话) 进程属于一个进程组

搜索引擎系列五:Lucene索引详解(IndexWriter详解、Document详解、索引更新)

一.IndexWriter详解 问题1:索引创建过程完成什么事? 分词.存储到反向索引中 1. 回顾Lucene架构图: 介绍我们编写的应用程序要完成数据的收集,再将数据以document的形式用lucene的索引API创建索引.存储. 这里重点要强调应用代码负责做什么,lucene负责做什么. 2. Lucene索引创建API 图示 通过该图介绍lucene创建索引的核心API:Document.IndexWriter Lucene中要索引的文档.数据记录以document表示,应用程序通过I

搜索引擎系列 -lucene简介 创建索引和搜索初步步骤

一.什么是Lucene? Lucene最初是由Doug Cutting开发的,2000年3月,发布第一个版本,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎 :Lucene得名于Doug妻子的中名,同时这也她外祖母的姓;目前是Apache基金会的一个顶级项目,同时也是学习搜索引擎入门必知必会. Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作. 优点:成熟的解决方案,有很多的成功案例.apache 顶级项目,正在持续快速的进步.庞大而活跃的开

lucene学习-创建索引

本文的lucene是基于lucene3.5版本. 使用lucene实现搜索引擎开发,核心的部分是建立索引和搜索.本节主要是记录创建索引部分的内容. 创建的索引结构如图所示. 创建索引的步骤分为以下几个步骤: 1.建立索引器IndexWriter 2.创建文档对象Document 3.建立信息对象字段Field 4.将Field对象添加到Document 5.将Document对象添加到IndexWriter对象中 下面简要介绍几个核心对象. (1).创建IndexWriter对象. IndexW

创建索引的方法有两种

创建索引的方法有两种:创建表的同时创建索引,在已有表上创建索引. 方法一:创建表的同时创建索引. 使用这种方法创建索引时,可以一次性地创建一个表的多个索引(例如唯一性索引.普通索引.复合索引等),其语法格式与创建的语法格式基本相同(注意粗体字部分的代码). Create  table 表名( 字段名1数据类型 [约束条件] 字段名字2   数据类型 [约束条件] - [unique][fulltext] index [索引名](字段名[(长度)] [asc|desc]) )engine=存储引擎

搜索引擎系列 ---lucene简介 创建索引和搜索初步

一.什么是Lucene? Lucene最初是由Doug Cutting开发的,2000年3月,发布第一个版本,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎 :Lucene得名于Doug妻子的中名,同时这也她外祖母的姓;目前是Apache基金会的一个顶级项目,同时也是学习搜索引擎入门必知必会. Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作. 优点:成熟的解决方案,有很多的成功案例.apache 顶级项目,正在持续快速的进步.庞大而活跃的开

一步一步跟我学习lucene(6)---lucene索引优化之多线程创建索引

这两天工作有点忙,博客更新不及时,请大家见谅: 前面了解到lucene在索引创建的时候一个IndexWriter获取到一个读写锁,这样势在lucene创建大数据量的索引的时候,执行效率低下的问题: 查看前面文档一步一步跟我学习lucene(5)---lucene的索引构建原理可以看出,lucene索引的建立,跟以下几点关联很大: 磁盘空间大小,这个直接影响索引的建立,甚至会造成索引写入提示完成,但是没有同步的问题: 索引合并策略的选择,这个类似于sql里边的批量操作,批量操作的数量过多直接影响执