Java框架------Lucene(二)

四、分词

所谓的分词,就是将一段文本,根据一定的规则,拆分成一个一个词。

Lucene是根据分析器实现分词的。针对不同的语言提供了不同的分析器。并且提供了一个通用的标准分析器StandardAnalyzer。

分词是全文检索的核心

4.1索引库结构

 

1df45b6158971150507dc9680d26209bdd2.jpg

从上图中,我们发现:

(1)索引库中有两个区域:索引区、文档区。

(2)文档区存放的是文档。Lucene给每一个文档自动加上一个文档编号docID。

(3)索引区存放的是索引。注意:

索引是以域为单位的,不同的域,彼此相互独立。

索引是根据分词规则创建出来的,根据索引就能找到对应的文档。

4.2、Field域

问题:我们已经知道,Lucene是在写入文档时,完成分词、索引的。那Lucene是怎么知道的呢?

答:Lucene是根据文档中的域的属性,来确定是否要分词、创建索引的。所以,我们必须搞清楚域有哪些属性。

4.2.1 三大属性

(1)是否分词(tokenized)

只有设置了分词属性为true,lucene才会对这个域进行分词处理。

在实际的开发中,有一些字段是不需要分词的,比如商品id,商品图片等。

而有一些字段是必须分词的,比如商品名称,描述信息等。

(2)是否索引(indexed)

只有设置了索引属性为true,lucene才为这个域的Term词创建索引。

在实际的开发中,有一些字段是不需要创建索引的,比如商品的图片等。我们只需要对参与搜索的字段做索引处理。

(3)是否存储(stored)

只有设置了存储属性为true,在查找的时候,才能从文档中获取这个域的值。

在实际开发中,有一些字段是不需要存储的。比如:商品的描述信息。

因为商品描述信息,通常都是大文本数据,读的时候会造成巨大的IO开销。而描述信息是不需要经常查询的字段,这样的话就白白浪费了cpu的资源了。

因此,像这种不需要经常查询,又是大文本的字段,通常不会存储到索引库。

4.2.2、Field常用类型

91cbb49b027e91c4e1b719f127c1263201a.jpg

将Lucene(一)中的BookDao的getDocument方法进行修改

public List<Document> getDocument(List<UBook> books) {
		//创建Document对象及其集合
		List<Document> docList = new ArrayList<>();
		Document doc = null;
		for (UBook book : books) {
			//Document创建对象
			doc = new Document();
			//NO表示不显示
			//不分词,不索引,要存储
			Field id =new StoredField("id", book.getBookid().toString());
			//分词,索引,存储
			Field name = new TextField("name", book.getName().toString(), Store.YES);
			//分词,索引,存储
			Field price =new FloatField("price", book.getPrice(), Store.YES);
			//不分词,不索引,存储
			Field pic = new StoredField("pic", book.getPic().toString());
			//分词,索引,不存储
			Field description = new TextField("description", book.getDescription().toString(), Store.NO);
			doc.add(id);
			doc.add(name);
			doc.add(price);
			doc.add(pic);
			doc.add(description);
			docList.add(doc);
			
		}
		
		return docList;
		
	}

得到如下输出

a5c216e926c47a063976712c16c74097af5.jpg

4.3、添加索引

由于内容的更新,我们需要对索引进行增删改

4.3.1、删除索引

(1)删除单个索引

倒数第3个test

(2)清空索引库

倒数第2个test

4.3.2、更新索引

先删除满足条件的索引,再添加新的索引

倒数第1个test

package textpage;

import java.io.File;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
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.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

import dao.BookDao;
import pdjo.UBook;

public class Text {
	
	@Test
	public void testName() throws Exception {
		BookDao bookDao = new BookDao();
		List<UBook> books = bookDao.getAll();
		for (UBook uBook : books) {
			System.out.println("id="+uBook.getBookid()+"name="+uBook.getName());
		}
	}
	//创建索引库
	@Test
	public void testLcene() throws Exception {
		
		BookDao dao = new BookDao();
		//分析文档,对文档中的field域进行分词
		Analyzer analyzer = new StandardAnalyzer();
		//创建索引
		//1)创建索引库目录
		Directory directory = FSDirectory.open(new File("C:\\lucene\\3"));
		//2创建IndexWriterConfig对象
		IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
		//3.创建IndexWriter对象
		IndexWriter writer = new IndexWriter(directory, config);
		//4.通过IndexWriter对象添加文档对象
		writer.addDocuments(dao.getDocument(dao.getAll()));
		//5.关闭IndexWriter
		writer.close();
		System.out.println("索引库创建成功");
	}
	//执行搜索
	@Test
	public void testLucene1() throws Exception {
		//1.创建查询(Query对象,即构建查询对象)
		//创建分析器
		Analyzer analyzer = new StandardAnalyzer();
		//确定索引的
		QueryParser queryParser = new QueryParser("name", analyzer);
		//
		Query query = queryParser.parse("name:lucene");
		//2.读取索引库
		//2.1指定搜索目录directory
		Directory directory = FSDirectory.open(new File("C:\\lucene\\3"));
		//2.2读取索引
		IndexReader reader = DirectoryReader.open(directory);
		//2.3索引库查询
		IndexSearcher searcher = new IndexSearcher(reader);
		//3.获得记录
		//3.1参数一,查询对象;参数二,指定返回的最大记录
		TopDocs topDocs = searcher.search(query, 10);
		//获得返回记录
		ScoreDoc [] scoreDocs = topDocs.scoreDocs;
		for (ScoreDoc scoreDoc : scoreDocs) {
			//获得id
			int docID = scoreDoc.doc;
			Document doc = searcher.doc(docID);
			System.out.println("索引ID"+docID);
			System.out.println("编号"+doc.get("id"));
			System.out.println("名称"+doc.get("name"));
			System.out.println("价格"+doc.get("price"));
			System.out.println("图片"+doc.get("pic"));
			System.out.println("描述"+doc.get("description"));
			
		}
		reader.close();
	}
	
	//删除指定索引
	@Test
	public void testdel() throws Exception {
		//1.指定索引库目录
		Directory directory = FSDirectory.open(new File("C:\\lucene\\3"));
		//2.创建
		IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
		//3.创建IndexWriter
		IndexWriter writer = new IndexWriter(directory, cfg);
		//4.通过IndexWriter来删除索引
		writer.deleteDocuments(new Term("name", "lucene"));
		writer.close();
		System.out.println("删除成功");
		
	}
	//清空索引库
	@Test
	public void testdelall() throws Exception {
		//1.指定索引库目录
		Directory directory = FSDirectory.open(new File("C:\\lucene\\3"));
		//2.创建
		IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
		//3.创建IndexWriter
		IndexWriter writer = new IndexWriter(directory, cfg);
		//4.通过IndexWriter删除索引
		writer.deleteAll();
		writer.close();
		System.out.println("索引库清空成功");
	}
	//更新索引
	//先删除满足条件的索引,再添加新的索引
	@Test
	public void testupdate() throws Exception {
		//1.指定索引库目录
		Directory directory = FSDirectory.open(new File("C:\\lucene\\3"));
		//2.创建
		IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer());
		//3.创建
		IndexWriter writer = new IndexWriter(directory, config);
		//4.通过IndexWriter修改索引
		//a.创建修改后的对象
		Document document = new Document();
		//文件名称
		Field field = new StringField("name", "updateIndex",Store.YES);
		document.add(field);
		//修改指定索引为新的索引
		writer.updateDocument(new Term("name", "lucene"), document);
		//
		writer.close();
		System.out.println("更新成功");
	}	
	
}

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/4146666/blog/3076467

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值