3.5 实例讲解Lucene索引的结构设计
3.2节我们已经运行了一个Lucene建立索引的小程序,这一节我们就以这个小程序为例讲解一下Lucene建立索引的过程。
1 import java.nio.charset.StandardCharsets; 2 import java.nio.file.Files; 3 import java.nio.file.Paths; 4 import java.io.*; 5 6 import org.apache.lucene.analysis.standard.StandardAnalyzer; 7 import org.apache.lucene.document.Document; 8 import org.apache.lucene.document.Field; 9 import org.apache.lucene.document.StringField; 10 import org.apache.lucene.document.TextField; 11 import org.apache.lucene.index.IndexWriter; 12 import org.apache.lucene.index.IndexWriterConfig; 13 import org.apache.lucene.store.Directory; 14 import org.apache.lucene.store.FSDirectory; 15 import org.apache.lucene.util.Version; 16 17 /** 18 * @author csl 19 * @description: 20 * 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser 21 * 作用:简单的索引建立 22 */ 23 public class Indexer { 24 public static Version luceneVersion = Version.LATEST; 25 /** 26 * 建立索引 27 */ 28 public static void createIndex(){ 29 IndexWriter writer = null; 30 try{ 31 //1、创建Directory 32 //Directory directory = new RAMDirectory();//创建内存directory 33 Directory directory = FSDirectory.open(Paths.get("index"));//在硬盘上生成Directory00 34 //2、创建IndexWriter 35 IndexWriterConfig iwConfig = new IndexWriterConfig( new StandardAnalyzer()); 36 writer = new IndexWriter(directory, iwConfig); 37 //3、创建document对象 38 Document document = null; 39 //4、为document添加field对象 40 File f = new File("raw");//索引源文件位置 41 for (File file:f.listFiles()){ 42 document = new Document(); 43 document.add(new StringField("path", f.getName(),Field.Store.YES)); 44 System.out.println(file.getName()); 45 document.add(new StringField("name", file.getName(),Field.Store.YES)); 46 InputStream stream = Files.newInputStream(Paths.get(file.toString())); 47 document.add(new TextField("content", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));//textField内容会进行分词 48 //document.add(new TextField("content", new FileReader(file))); 如果不用utf-8编码的话直接用这个就可以了 49 writer.addDocument(document); 50 } 51 }catch(Exception e){ 52 e.printStackTrace(); 53 }finally{ 54 //6、使用完成后需要将writer进行关闭 55 try { 56 writer.close(); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 } 61 } 62 public static void main(String[] args) throws IOException 63 { 64 createIndex(); 65 } 66 }
创建索引共六步:
1.创建索引目录。
Directory directory = new RAMDirectory(); Directory directory = FSDirectory.open(Paths.get("index"));
创建索引目录有两种方式:
- RAMDirectory类:创建一个内存目录,优点是速度快,缺点是程序退出后索引目录数据就会丢失。
- FSDirectory类: 创建一个文件目录,该方式创建的索引数据保存在磁盘上,不会因为程序的退出而消失。
下文针对FSDirectory方式来讲解Lucene的基本使用。
2.创建IndexWriter。
1 IndexWriterConfig iwConfig = new IndexWriterConfig( new StandardAnalyzer()); 2 IndexWriter writer = new IndexWriter(directory, iwConfig);
通过IndexWriter对象来创建和维护索引。
IndexWriterConfig对象用来对IndexWriter进行初始配置:配置分词器;配置索引维护的方式;配置用来缓冲文档的RAM大小等。
具体可参照IndexWriterrConfig文档根据需求进行个性化配置。
3. 创建Document。
1 Document doc=new Document();
Document是Lucene建立索引的基本单元,相当于数据库的关系表。
4. 添加Field。
1 document = new Document(); 2 document.add(new StringField("path", f.getName(),Field.Store.YES)); 3 System.out.println(file.getName()); 4 document.add(new StringField("name", file.getName(),Field.Store.YES)); 5 InputStream stream = Files.newInputStream(Paths.get(file.toString())); 6 document.add(new TextField("content", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));//textField内容会进行分词 7 //document.add(new TextField("content", new FileReader(file))); 如果不用utf-8编码的话直接用这个就可以了
Field是Lucene建立索引的最小单元,相当于关系表中的属性。一个Document可以包含多个Field。Document添加Field只需调用Add()方法。
Lucene为我们提供了多种类型的Field,比如IntField, LongField, StringField, TextField等。程序实例中,我们用到了StringField和TextField。我们有必要来了解一下这两种Field的区别,因为这关系到倒排表的建立:
- StringField:对域进行索引,但不进行分词,将域值作为单一的语汇单元,适用于索引那些不能被分解的域值,如URL,文件路径,电话号码等。参考StringField文档。
- TextField: 对域既索引又分词,Lucene会对这个域进行分词并建立倒排表。参考TextField文档。
5.添加Document。
对IndexWriter对象调用addDocument方法将文档添加到索引库中。
6.关闭IndexWriter对象。
把所有的文档都添加到索引库中后,关闭Indexwriter对象。
ps:这篇博客以文集为例形象生动地说明了IndexWriter,Document和Field的关系,大家不妨看一看:例子
关于Lucene的具体索引步骤就介绍到这里~~
.