`
liaokang.java
  • 浏览: 155449 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

lucene入门

阅读更多
lucene是一个高性能,可伸缩的全文搜索工具包,可以使用它为你的应用程序添加索引和搜索能力,下面是一个建立索引,并对索引进行查询的小例子

package com.lamp.lucene.util;

import java.io.File;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.NumberTools;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.junit.Test;

public class IndexDaoTest {

	// 需要建立索引的数据源目录
	public String dataPath = "D:\\javaEEProject\\Lucene\\dataPath";

	// 具体的数据源文件路径
	public String filePath = "D:\\javaEEProject\\Lucene\\dataPath\\JDBC.txt";
	public String filePath2 = "D:\\javaEEProject\\Lucene\\dataPath\\反射机制.txt";

	public IndexDao indexDao = new IndexDao();

	/**
	 * 对数据源文件建立索引
	 */
	@Test
	public void testSave() throws Exception {
		File file = new File(dataPath);
		traverseFile(file);
	}

	/**
	 * 对目录下的文件进行遍历并对后缀为.txt的文件建立索引
	 */
	public void traverseFile(File file) throws Exception {
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (File f : files) {
				traverseFile(f);
			}
		}
		if (file.getName().endsWith(".txt")) {
			Document doc = FileToDocument.fileToDocument(file);
			indexDao.save(doc);
		}

	}

	/**
	 * 删除指定文件的索引文件
	 */
	@Test
	public void testDelete() {
		Term term = new Term("path", filePath);
		indexDao.delete(term);
	}

	/**
	 * 更新指定文件的索引
	 */
	@Test
	public void testUpdate() throws Exception {
		Term term = new Term("path", filePath);
		Document doc = FileToDocument.fileToDocument(filePath);
		doc.getField("content").setValue("这是更新后的文件内容");
		indexDao.update(term, doc);
	}

	/**
	 * 根据关键字对索引文件进行查询
	 */
	@Test
	public void testSearch() {
		String queryString = "操作";
		// search(queryString, 0, 10)说的是从第一条匹配结果开始,返回最多前10条记录
		QueryResult qr = indexDao.search(queryString, 0, 10);
		System.out.println("总共有" + qr.getRecordCount() + "条匹配结果");
		for (Document doc : qr.getRecordList()) {
			System.out.println(doc.get("name"));
			System.out.println(doc.get("content"));
			System.out.println(NumberTools.stringToLong(doc.get("size")));
		}
	}

}




package com.lamp.lucene.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumberTools;

public class FileToDocument {

	//对其name,content字段建立索引
	public static Document fileToDocument(String dataPath) throws Exception {
		File file = new File(dataPath);
		Document doc = new Document();
		doc.add(new Field("name", file.getName(), Store.YES, Index.ANALYZED));
		doc.add(new Field("content", getContent(file), Store.YES,
				Index.ANALYZED));
		doc.add(new Field("size", NumberTools.longToString(file.length()), Store.YES,
				Index.NOT_ANALYZED));
		doc.add(new Field("path", file.getAbsolutePath(), Store.YES,
				Index.NOT_ANALYZED));
		return doc;

	}

	//返回文件内容
	private static String getContent(File file) throws Exception {
		StringBuffer buffer = new StringBuffer();
		BufferedReader reader = null;
		reader = new BufferedReader(new FileReader(file));
		String str = "";
		while (null != (str = reader.readLine())) {
			buffer.append(str).append("\n");
		}
		return buffer.toString();
	}

	public static Document fileToDocument(File file) throws Exception {
		Document doc = new Document();
		doc.add(new Field("name", file.getName(), Store.YES, Index.ANALYZED));
		doc.add(new Field("content", getContent(file), Store.YES,
				Index.ANALYZED));
		doc.add(new Field("size", NumberTools.longToString(file.length()), Store.YES,
				Index.NOT_ANALYZED));
		doc.add(new Field("path", file.getAbsolutePath(), Store.YES,
				Index.NOT_ANALYZED));
		return doc;
	}

}




package com.lamp.lucene.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jeasy.analysis.MMAnalyzer;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.NumberTools;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeFilter;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.Scorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;

public class IndexDao {

	public String indexPath = "D:\\javaEEProject\\Lucene\\indexPath";

	public Analyzer analyzer = new MMAnalyzer();// 词库分词

	/**
	 * 添加/创建索引
	 */
	public void save(Document doc) {
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(indexPath, analyzer,
					MaxFieldLength.LIMITED);
			indexWriter.addDocument(doc);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (indexWriter != null) {
					indexWriter.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Term是搜索的最小单位,代表某个 Field 中的一个关键词,如:<title, lucene>
	 * new Term( "title", "lucene" );
	 * new Term( "id", "5" );
	 * new Term( "id", UUID );
	 */
	public void delete(Term term) {
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(indexPath, analyzer,
					MaxFieldLength.LIMITED);
			indexWriter.deleteDocuments(term);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				indexWriter.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 更新索引
	 * 
	 * <pre>
	 * indexWriter.deleteDocuments(term);
	 * indexWriter.addDocument(doc);
	 * </pre>
	 * 
	 * @param term
	 * @param doc
	 */
	public void update(Term term, Document doc) {
		IndexWriter indexWriter = null;
		try {
			indexWriter = new IndexWriter(indexPath, analyzer,
					MaxFieldLength.LIMITED);
			indexWriter.updateDocument(term, doc);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				indexWriter.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * <pre>
	 * totalPage = recordCount / pageSize;
	 * if (recordCount % pageSize &gt; 0)
	 * 	totalPage++;
	 * </pre>
	 * 
	 */
	/*
	 * public QueryResult search(String queryString, int firstResult, int
	 * maxResults) { try { // 1,把要搜索的文本解析为 Query String[] fields = { "name",
	 * "content" }; Map<String, Float> boosts = new HashMap<String, Float>();
	 * boosts.put("name", 3f); // boosts.put("content", 1.0f); 默认为1.0f
	 * 
	 * QueryParser queryParser = new MultiFieldQueryParser(fields, analyzer,
	 * boosts); Query query = queryParser.parse(queryString);
	 * 
	 * return search(query, firstResult, maxResults); } catch (Exception e) {
	 * throw new RuntimeException(e); } }
	 */

	public QueryResult search(String queryString, int firstResult,
			int maxResults) {
		try {
			//在索引字段name,content上进行查询
			String[] fields = { "name", "content" };
			// 设置字段相关度,默认相关度为1f
			Map<String, Float> boosts = new HashMap<String, Float>();
			boosts.put("name", 5f);

			QueryParser queryParser = new MultiFieldQueryParser(fields,
					analyzer,boosts);
			// 1,把要搜索的文本解析为 Query
			Query query = queryParser.parse(queryString);

			return search(query, firstResult, maxResults);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public QueryResult search(Query query, int firstResult, int maxResults) {
		IndexSearcher indexSearcher = null;

		try {
			// 2,进行查询
			indexSearcher = new IndexSearcher(indexPath);
			//限定所查询文件的大小在200-1000之间
			Filter filter = new RangeFilter("size",
					NumberTools.longToString(200),
					NumberTools.longToString(1000), true, true);

			// 自定义排序,此处是按照文档大小进行排序
			Sort sort = new Sort();
			sort.setSort(new SortField("size")); // 默认为升序
			// sort.setSort(new SortField("size", true));此为降序
			
			//TopDocs topDocs = indexSearcher.search(query, filter, 10000, sort);
			
			TopDocs topDocs = indexSearcher.search(query, null, 10000, sort);
			//查询到的匹配结果数
			int recordCount = topDocs.totalHits;
			List<Document> recordList = new ArrayList<Document>();

			// 准备高亮器,所谓高亮就是对查询到的关键字进行字体颜色的改变或者为其设置超链接
			Formatter formatter = new SimpleHTMLFormatter("<font color='red'>",
					"</font>");
			Scorer scorer = new QueryScorer(query);
			Highlighter highlighter = new Highlighter(formatter, scorer);

			Fragmenter fragmenter = new SimpleFragmenter(50);
			highlighter.setTextFragmenter(fragmenter);

			// 3,取出当前页的数据
			int end = Math.min(firstResult + maxResults, topDocs.totalHits);
			for (int i = firstResult; i < end; i++) {
				ScoreDoc scoreDoc = topDocs.scoreDocs[i];
				// 文档内部编号
				int docSn = scoreDoc.doc; 
				// 根据编号取出相应的文档
				Document doc = indexSearcher.doc(docSn); 
				// 返回高亮后的结果,如果当前属性值中没有出现关键字,会返回 null
				String hc = highlighter.getBestFragment(analyzer, "content",
						doc.get("content"));
				if (hc == null) {
					String content = doc.get("content");
					int endIndex = Math.min(50, content.length());
					// 最多前50个字符
					hc = content.substring(0, endIndex);
				}
				doc.getField("content").setValue(hc);
				recordList.add(doc);
			}

			// 返回结果
			return new QueryResult(recordCount, recordList);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				indexSearcher.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}




package com.lamp.lucene.util;

import java.util.List;

import org.apache.lucene.document.Document;

/**
 * 
 * QueryResult封装的是匹配结果数和Document集合
 */
public class QueryResult {
	private int recordCount;
	private List<Document> recordList;

	public QueryResult(int recordCount, List<Document> recordList) {
		super();
		this.recordCount = recordCount;
		this.recordList = recordList;
	}

	public int getRecordCount() {
		return recordCount;
	}

	public void setRecordCount(int recordCount) {
		this.recordCount = recordCount;
	}

	public List<Document> getRecordList() {
		return recordList;
	}

	public void setRecordList(List<Document> recordList) {
		this.recordList = recordList;
	}

}



当然除了关键字查询外,还有文件大小范围进行查询,通配符查询,短语查询,布尔查询,示例如下

package com.lamp.lucene.util;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.NumberTools;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.junit.Test;


public class QueryTest {
	
	public IndexDao indexDao = new IndexDao();

	/**
	 * 关键字查询,即对指定的列上进行查询
	 */
	@Test
	public void testTermQuery(){
		Term term = new Term("name", "反射");
		Query query = new TermQuery(term);
		QueryResult result = indexDao.search(query, 0, 100);
		printResult(result);
	}

	/**
	 * 按照文件大小范围进行查询,由于数字字符串比较大小时由于位数不同易产生问题,这里统一将数字用工具类
	 * NumberTools.longToString(long a)进行转化
	 */
	@Test
	public void testRangeQuery(){
		Term lowerTerm = new Term("size",NumberTools.longToString(200));
		Term upperTerm = new Term("size",NumberTools.longToString(1000));
		
		Query query = new RangeQuery(lowerTerm, upperTerm, true);
		QueryResult result = indexDao.search(query, 0, 100);
		printResult(result);
	}
	
	/**
	 * 通配符查询
	 * ‘?’代表一个字符,‘*’代表0个或多个字符
	 */
	@Test
	public void testWildcardQuery(){
		Term term = new Term("name","jd*");
		Query query = new WildcardQuery(term);
		QueryResult result = indexDao.search(query, 0, 100);
		printResult(result);
	}
	
	/**
	 * 短语查询,比如你想查一首歌曲,里面有两个词语,但是这两个词语之间又隔着若干个词语,这时候可以选择短语查询
	 */
	@Test
	public void testPhraseQuery(){
		PhraseQuery query = new PhraseQuery();
		query.add(new Term("content","反射"));
		query.add(new Term("content","属性"));
		//设定最大间隔数为10
		query.setSlop(10);
		QueryResult result = indexDao.search(query, 0, 100);
		printResult(result);
	}
	/**
	 * 布尔查询,即对查询条件进行多项指定,不如大小,内容等
	 */
	@Test
	public void testBoolQuery(){
		Term lowerTerm = new Term("size",NumberTools.longToString(200));
		Term upperTerm = new Term("size",NumberTools.longToString(1000));
		Query query1 = new RangeQuery(lowerTerm, upperTerm, true);
		
		PhraseQuery query2 = new PhraseQuery();
		query2.add(new Term("content","反射"));
		query2.add(new Term("content","属性"));
		//设定最大间隔数为10 
		query2.setSlop(10);
		
		BooleanQuery booleanQuery = new BooleanQuery();
		//Occur.MUST指定的条件必须满足
		booleanQuery.add(query1, Occur.MUST);
		booleanQuery.add(query2, Occur.MUST);
		QueryResult result = indexDao.search(booleanQuery, 0, 100);
		printResult(result);
	}
	
	public void printResult(QueryResult result) {
		System.out.println("找到的匹配结果有:" + result.getRecordCount() + "条");
		for(Document doc : result.getRecordList()){
			System.out.println(doc.get("name"));
			System.out.println(doc.get("content"));
		}
	}
	
}



我使用的lucene版本是2.4,引入的jar包有lucene-core-2.4.0.jar,lucene-highlighter-2.4.0.jar,lucene-analyzers-2.4.0.jar,je-analysis-1.5.3.jar
分享到:
评论

相关推荐

    Lucene入门与使用

    Lucene入门与使用,非常简单,适合入门

    lucene 入门

    `lucene入门小实例.txt` 文件中可能包含了一个简单的Lucene使用示例,例如: 1. 创建 `Directory` 对象,比如使用 `FSDirectory.open()` 打开一个文件系统的目录来存储索引。 2. 实例化 `Analyzer`,如使用 `...

    lucene入门小例子

    这个“lucene入门小例子”很可能是为了帮助初学者理解并掌握Lucene的基本用法而设计的一系列示例代码。 Lucene的核心概念包括索引、文档、字段和查询。首先,你需要理解索引的概念,它类似于传统数据库中的索引,但...

    lucene 入门资料包

    以上是Lucene入门的基本知识和关键概念,通过深入学习和实践,你可以掌握如何利用Lucene构建强大的全文搜索引擎。记住,实践中遇到的问题往往是最好的学习资源,不断尝试和解决,你将逐渐成为Lucene的专家。

    Lucene入门学习文档

    **Lucene入门学习文档** **一、什么是Lucene** Lucene是Apache软件基金会下的一个开源全文检索库,它提供了一个高性能、可扩展的信息检索服务。Lucene最初由Doug Cutting开发,现在已经成为Java社区中事实上的标准...

    [Lucene] Lucene入门心得

    【Lucene】Lucene入门心得 Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发,被广泛应用于各种搜索引擎的构建。它提供了一个简单的API,使得开发者可以方便地在自己的应用程序中集成全文检索功能。...

    全文搜索引擎lucene入门

    **全文搜索引擎Lucene入门** 全文搜索引擎Lucene是Apache软件基金会的一个开放源代码项目,它为Java开发者提供了一个高性能、可扩展的信息检索库。Lucene以其强大的文本搜索功能和高效的索引能力,在各种需要全文...

    lucene入门到项目开发.docx

    《Lucene入门到项目开发》 Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发,被广泛应用于各种搜索引擎的构建。它提供了一个简单但功能强大的API,可以帮助开发者快速实现对文本数据的检索和分析。 一...

    lucene入门基础教程

    ### Lucene 入门基础教程知识点详解 #### 一、Lucene简介 - **定义**:Lucene是一款高性能、全功能的文本搜索引擎库,由Java编写而成,属于Apache项目的一部分。 - **适用场景**:适合于任何需要进行全文检索的应用...

    一个经典Lucene入门模块及例子解析

    在这个经典Lucene入门模块中,我们将深入理解如何使用Lucene进行索引创建和搜索操作。 首先,我们来看Lucene如何建立数据的索引。这通常涉及以下几个步骤: 1. **索引创建**:使用 `IndexWriter` 对象来创建或更新...

    Lucene入门demo

    这个“Lucene入门demo”将帮助我们理解如何使用 Lucene 进行基本的索引和搜索操作。 **一、Lucene 的核心概念** 1. **索引(Indexing)**: 在 Lucene 中,索引是文档内容的预处理结果,类似于数据库中的索引。通过...

    lucene入门指南

    **Lucene 入门指南** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发并维护。它是 Java 开发人员用来构建搜索引擎应用程序的基础工具。本指南将帮助初学者理解 Lucene 的核心概念,以及如何利用它来...

    lucene入门体会

    【Lucene 入门体会】 Lucene 是一个强大的全文检索工具包,主要由 Java 编写,它提供了索引和搜索功能,使得开发者能够轻松地为应用程序添加高级搜索能力。作为Apache Jakarta家族的一员,Lucene 开源且免费,被...

    Lucene入门指南

    ### Lucene入门指南 #### 一、Lucene简介 **Lucene** 是一款高性能的全文检索引擎工具包,由 **Apache 软件基金会** 的 **Jakarta 项目组** 开发并维护。作为一款完全开放源代码的工具,Lucene 提供了一系列的功能...

    lucene入门知识

    【Lucene入门知识详解】 Lucene是一个基于Java的全文索引引擎工具包,它并不是一个完整的全文搜索引擎,而是提供了一套构建搜索引擎的基础组件。Lucene的主要目标是方便开发者将其集成到各类应用程序中,以实现高效...

Global site tag (gtag.js) - Google Analytics