博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lucene检索的一系列流程
阅读量:4187 次
发布时间:2019-05-26

本文共 4720 字,大约阅读时间需要 15 分钟。

介绍了Lucene检索的一系列流程,本篇来看下Lucene中一个特殊的Directory的实现之FileSwitchDirectory,顾名思义,从字面上的意思来理解是一个基于文件目录切换的一个实现,实际上也正是如此。
那么,此类的作用是什么呢? 我们都知道lucene的索引文件是非常松散灵活的,各个文件格式之间相互独立而又有联系,在Lucenen检索的时候,会并行的打开所有的段文件,然后合并结果集至一个公共队列里返回。
Lucene的Directory基类,提供了非常丰富的子类实现,为什么如此呢,其实跟不同的操作系统和平台有紧密的联系,所以在我们的代码里,经常会使用FSDirectory的静态方法来打开一个能在我们所使用的平台上发挥最大优势的Directory,在源码里我们可以发现这个方法里面是对主流的操作系统进行了判断和选择后,会给我们返回一个合适的Directory,可能这个方法在不同的操作平台上返回不一样的Directory的实现,这一点是很正常的。
Java代码 复制代码 收藏代码
1.public static FSDirectory open(File path, LockFactory lockFactory) throws IOException {
2. if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX)
3. && Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
4. return new MMapDirectory(path, lockFactory);
5. } else if (Constants.WINDOWS) {
6. return new SimpleFSDirectory(path, lockFactory);
7. } else {
8. return new NIOFSDirectory(path, lockFactory);
9. }
10. }
FileSwitchDirectory的出现,可以使我们组合不同Directory的优点,来充分利用我们的系统资源,我们都知道使用内存索引RAMDirectory来访问索引其速度和效率都是非常优异的,然后,有时候我们的数据量大的惊人,以至于内存中根本放不下这个索引文件,那么这时候我们既想获取高效的索引访问性能,又想获取读取和检索大索引的优异的并发性能,这时候我们怎么做呢?
这时候就是该FileSwitchDirectory大显身手的时候了,利用这个类,我们可以轻而易举的结合任意2个Directory的优异点,来为我们所用,下面我们先来看下FileSwitchDirectory在源码里的构造实现。
Java代码 复制代码 收藏代码
1./**
2. * @param primaryExtensions 由主索引负责打开的文件
3. * @param primaryDir 主索引目录
4. * @param secondaryDir 从索引目录
5. * @param doClose 是否在关闭时关闭所有Directory的资源
6. * **/
7. public FileSwitchDirectory(Set<String> primaryExtensions, Directory primaryDir, Directory secondaryDir, boolean doClose) {
8. this.primaryExtensions = primaryExtensions;
9. this.primaryDir = primaryDir;
10. this.secondaryDir = secondaryDir;
11. this.doClose = doClose;
12. this.lockFactory = primaryDir.getLockFactory();
13. }
由构造方法可以看出FileSwitchDirectory是需要2个Directory的实现才可以组装起来,而通过第一个参数我们可以指定主索引需要加载的索引文件,其它的将会由从Directory来实现,由此达到,快速切换不同的Directory来获取他们各自的优点。
一般情况下我们会将fdt和fdx文件放在NIODirectory里,因为这两个文件分别存储的是文档的正向信息包含具体的term,fdx文件是fdt文件的一个索引文件,实际上在后来,所有的文本数据都会保存在fdt里,索引在索引非常大的时候,这两个文件是最占容量的,所以我们选择将此放入NIO中,由此来访问大索引信息,其他的一些段信息文件,字典文件,放入内存索引中由此来获取更高的检索效率。
下面是散仙的一个示例的索引截图:
注意上图中可能大家会发现tim的项词典文件,也挺大的,散仙在这里解释一下,散仙在索引只索引了2个非常短的字段,然后循环添加了1万次,在实际项目中,肯定是多个字段组成且文本内容会比较多,那个时候索引出来的数据fdt文件一般都是最大的数据文件。
实现切换索引的代码如下:
Java代码 复制代码 收藏代码
1.String path="E:\\1111111111111111111\\1\\";
2. try{
3. //添加放置在nio文件里的索引文件
4. Set<String> files=new HashSet<>();
5. files.add("fdt");
6. files.add("fdx");
7.
8. Directory d1=FSDirectory.open(new File(path));//装载磁盘索引
9. RAMDirectory map=new RAMDirectory(d1,IOContext.READ);//放置内存索引
10. NIOFSDirectory nio=new NIOFSDirectory(new File(path));//基于并发大文件的NIO索引
11. FileSwitchDirectory fsd=new FileSwitchDirectory(files,nio,map,true); //切换实现
12. for(String s:fsd.listAll()){
13. //System.out.println(s);
14. System.out.println("文件:"+s+" 读取类型: "+fsd.getDirectory(s));
15.
16. }
运行效果如下所示:
Java代码 复制代码 收藏代码
1.文件:_2.si 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
2.文件:_2_Lucene41_0.tim 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
3.文件:segments.gen 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
4.文件:_2.fdt 读取类型: org.apache.lucene.store.NIOFSDirectory@E:\1111111111111111111\1 lockFactory=org.apache.lucene.store.NativeFSLockFactory@37263a93
5.文件:segments_2 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
6.文件:_2_Lucene41_0.doc 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
7.文件:_2_Lucene41_0.tip 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
8.文件:_2.fdx 读取类型: org.apache.lucene.store.NIOFSDirectory@E:\1111111111111111111\1 lockFactory=org.apache.lucene.store.NativeFSLockFactory@37263a93
9.文件:_2.fnm 读取类型: org.apache.lucene.store.RAMDirectory@6a059fa4 lockFactory=org.apache.lucene.store.SingleInstanceLockFactory@1733fe5d
由输出结果,我们可以看出除了fdt文件和fdx文件是从NIO里打开的,其他的都会被加载到RAM里,与我们预期的假设是一致的。
最后我们来简单分析下,Lucene是如何实现索引的动态的切换?
实际上在程序一开始启动时,是打开了2个Directory,然后通过FileSwitchDirectory 组装在了一起,在一个检索请求发来时,会选择具体的索引文件打开并读取,此时就是切换目录的时候,我们可以在FileSwitchDirectory 的源码里找到如下的一段代码:
Java代码 复制代码 收藏代码
1./**
2. * 切换目录的核心代码
3. * @param name 具体的索引文件名
4. * @return 返回的具体Directory
5. * ***/
6. public Directory getDirectory(String name) {
7. String ext = getExtension(name);
8. if (primaryExtensions.contains(ext)) {//在初始化的集合里判断
9. return primaryDir;//true,将会从主索引加载
10. } else {
11. return secondaryDir;//false将会从从索引加载
12. }
13. }
其实,就是在启动的时候打开了同一份索引的2个不同的Directory的实现,然后通过FileSwitchDirectory 这个类,来动态的完成的索引切换的过程

转载地址:http://dwnoi.baihongyu.com/

你可能感兴趣的文章
Designing and Implement ButtonEdit Control for Windows Forms
查看>>
如果你是程序员你或许不须以撰写组件维生,但我确信你必定得依赖组件维生!
查看>>
像Component的Control
查看>>
Inside ASP.NET 2.0-即时编译系统
查看>>
修復VS.NET 2005
查看>>
LINQ
查看>>
JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载]
查看>>
学英语的网站[转载]
查看>>
Asp.net 2.0 自定义控件开发[开发一个图表(WebChart)控件(柱状图示例)](示例代码下载)
查看>>
住在我隔壁储藏室的大学刚毕业的小夫妻[转载]
查看>>
英语学习加油站[收集]
查看>>
Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSource属性, 能够自动识别不同数据源](示例代码下载)
查看>>
2007.5.13 祝天下所有的母亲: 节日快乐!
查看>>
Asp.net 2.0自定义控件开发相关的几种嵌入资源解决方案
查看>>
Asp.net 2.0控件开发相关调试(JavaScript调试和自定义控件设计时调试)
查看>>
Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
查看>>
Asp.net 2.0自定义控件(点击HyperLink后执行事件)[网友问题: DataList里HyperLink控件激发事件,在哪定义?]
查看>>
Asp.net 2.0 自定义控件开发[实现自动计算功能(AutoComputeControl)][示例代码下载]
查看>>
[转载]《越狱》第二季过后,剧情跌宕起伏,各角色们的命运也各有不同,现公布如下
查看>>
Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
查看>>