- 浏览: 1034376 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1441)
- 软件思想&演讲 (9)
- 行业常识 (250)
- 时时疑问 (5)
- java/guava/python/php/ruby/R/scala/groovy (213)
- struct/spring/springmvc (37)
- mybatis/hibernate/JPA (10)
- mysql/oracle/sqlserver/db2/mongdb/redis/neo4j/GreenPlum/Teradata/hsqldb/Derby/sakila (268)
- js/jquery/jqueryUi/jqueryEaseyUI/extjs/angulrJs/react/es6/grunt/zepto/raphael (81)
- ZMQ/RabbitMQ/ActiveMQ/JMS/kafka (17)
- lucene/solr/nuth/elasticsearch/MG4J (167)
- html/css/ionic/nodejs/bootstrap (19)
- Linux/shell/centos (56)
- cvs/svn/git/sourceTree/gradle/ant/maven/mantis/docker/Kubernetes (26)
- sonatype nexus (1)
- tomcat/jetty/netty/jboss (9)
- 工具 (17)
- ETL/SPASS/MATLAB/RapidMiner/weka/kettle/DataX/Kylin (11)
- hadoop/spark/Hbase/Hive/pig/Zookeeper/HAWQ/cloudera/Impala/Oozie (190)
- ios/swift/android (9)
- 机器学习&算法&大数据 (18)
- Mesos是Apache下的开源分布式资源管理框架 (1)
- echarts/d3/highCharts/tableau (1)
- 行业技能图谱 (1)
- 大数据可视化 (2)
- tornado/ansible/twisted (2)
- Nagios/Cacti/Zabbix (0)
- eclipse/intellijIDEA/webstorm (5)
- cvs/svn/git/sourceTree/gradle/jira/bitbucket (4)
- jsp/jsf/flex/ZKoss (0)
- 测试技术 (2)
- splunk/flunm (2)
- 高并发/大数据量 (1)
- freemarker/vector/thymeleaf (1)
- docker/Kubernetes (2)
- dubbo/ESB/dubboX/wso2 (2)
最新评论
介绍了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 这个类,来动态的完成的索引切换的过程
那么,此类的作用是什么呢? 我们都知道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 这个类,来动态的完成的索引切换的过程
发表评论
-
elasticsearch异常信息汇总
2017-11-06 09:34 15241.IndexMissingException 异常信息 ... -
Elasticsearch的架构
2018-03-22 10:30 496为什么要学习架构? Elasticsearch的一些架构 ... -
怎么在Ubuntu上打开端口
2017-10-21 20:45 0Netstat -tln 命令是用来查看linux的端口使用情 ... -
Elasticsearch工作原理
2018-03-22 10:30 436一、关于搜索引擎 各 ... -
Elasticsearch的路由(Routing)特性
2017-10-11 10:41 0Elasticsearch路由机制介 ... -
Elasticsearch中的segment理解
2017-10-11 09:58 1848在Elasticsearch中, 需要搞清楚几个名词,如se ... -
Elasticsearch的路由(Routing)特性
2017-09-28 16:52 606Elasticsearch路由机制介绍 Elastics ... -
Elasticsearch 的 Shard 和 Segment
2017-09-28 16:05 1185Shard(分片) 一个Shard就是一个Lu ... -
开源大数据查询分析引擎现状
2017-09-22 03:04 820大数据查询分析是云计算中核心问题之一,自从Google在20 ... -
大数据处理方面的 7 个开源搜索引擎
2017-09-22 03:01 479大数据是一个包括一切 ... -
开源大数据查询分析引擎现状
2017-09-23 11:26 536大数据查询分析是云计算中核心问题之一,自从Google在2 ... -
elasticsearch 把很多类型都放在一个索引下面 会不会导致查询慢
2017-09-25 09:45 973主要看数据量ES索引优 ... -
腾讯大数据Hermes爱马仕的系统
2017-09-23 11:15 956腾讯大数据最近做了几件事,上线了一个官方网站http:// ... -
配置高性能Elasticsearch集群的9个小贴士
2017-09-25 10:02 581Loggly服务底层的很多 ... -
Elasticsearch与Solr
2017-09-25 16:24 541Elasticsearch简介* Elasti ... -
大数据杂谈微课堂|Elasticsearch 5.0新版本的特性与改进
2017-09-26 09:57 795Elastic将在今年秋季的 ... -
ElasticSearch性能优化策略
2017-09-26 09:51 441ElasticSearch性能优化主 ... -
ES索引优化
2017-09-19 20:39 0ES索引优化篇主要从两个方面解决问题,一是索引数据过程;二是 ... -
分词与索引的关系
2017-09-19 20:33 0分词与索引,是中文搜索里最重要的两个技术,而且两者间是密不可 ... -
Elasticsearch中的segment理解
2017-09-19 20:30 0在Elasticsearch中, 需要搞清楚几个名词,如se ...
相关推荐
- **索引创建**:首先,Lucene会将文档内容解析成一系列的词条(Token),并对这些词条进行一定的预处理,如去除停用词、词干提取等。 - **索引存储**:经过处理后的词条会被存储到索引中。索引通常是以倒排表的形式...
5. **分词器(Tokenizer)**:用于将输入的文本分解成一系列的词或短语,是文本分析的第一步。 6. **查询解析器(Query Parser)**:处理用户的搜索请求,将其转化为Lucene可以理解的查询对象。 7. **评分...
### Lucene检索数据库支持中文检索 #### 一、Lucene简介与原理 ##### 1. Lucene概述 Lucene是一款高性能、全功能的文本搜索引擎库,由Java编写而成。其核心功能是为开发者提供构建搜索应用程序的基础框架。Lucene...
1. 分词(Tokenization):Lucene.NET首先通过分词器(Analyzer)将输入的文档分解成一系列的关键词(Token)。分词器会考虑语言特性,如英文中的单词边界,进行词汇切分。 2. 建立索引(Indexing):每个关键词会...
通过分析和分词,将文本转换为一系列可搜索的关键词,然后构建倒排索引,使得快速查找匹配文档变得可能。 2. **分词器(Tokenizer)**:分词器是将原始文本分割成独立的词汇单元(称为“术语”或“tokens”)的组件...
5. **分词器(Analyzer)**: 负责将输入的字符串分解成一系列的术语,对文本进行预处理,包括去除停用词、词干提取等。 6. **查询解析器(Query Parser)**: 将用户的查询字符串转化为Lucene能理解的查询对象,支持...
- **Analyzer**:文本分析器是Lucene处理文本的第一步,它负责将输入的字符串分解为一系列的词项(tokens)。在5.2.1版本中,包括了`StandardAnalyzer`和`SimpleAnalyzer`等,适用于不同语言和应用场景。 2. **...
- **分词器(Tokenizer)**:处理输入文本,将其拆分为一系列的词语。 - **词项(Token)**:索引的基本单位,通常是一个个独立的词语。 - **倒排索引(Inverted Index)**:存储每个词项在哪些文档中出现,以及...
Lucene的索引构建逻辑围绕一系列核心对象展开,如项(Term)、域(Field)、文档(Document)、段(Segment)等。了解这些对象及其相互关系,是掌握Lucene内部工作原理的关键。 - **项(Term)**:表示索引中的单个...
- **分词**:为了建立索引,首先需要将文档中的文本分割成一系列单词或词组,这个过程称为分词。 - **搜索**:用户可以通过输入查询语句来搜索索引,Lucene会返回匹配的结果。 #### Lucene的工作流程 - **索引过程...
第四部分聚焦于Lucene索引构建逻辑模块的分析,详细阐述了索引构建的流程,包括对象体系的UML图,展示了Lucene内部如何处理文档、字段和术语,以及如何通过一系列步骤将这些信息转化为可搜索的索引结构。 总体而言...
3. **分析器(Analyzer)**:分析器负责将输入的文本分解为一系列的词元(Token),并进行标准化处理,如去除停用词、词形还原等。Lucene提供了多种预设分析器,也可自定义。 4. **查询解析器(Query Parser)**:...
3. 分词器(Analyzer):分词器负责将文档字段的文本进行分词处理,生成一系列的关键词,这是Lucene索引的基础。不同的语言和应用场景需要选择合适的分词器。 4. 索引(Index):索引是Lucene的核心,类似于关系...
1. **创建索引**:这是Lucene工作的第一步,它会把文档内容解析成一系列的术语(tokens),然后为每个术语建立倒排索引。倒排索引是一种数据结构,它允许快速查找包含特定术语的文档。 2. **索引写入**:在创建索引...
- **分词器(Tokenizer)**:分词器将输入的文本分解为一系列的词语,这是建立索引的第一步。 - **分析器(Analyzer)**:分析器结合了分词器、过滤器等,负责对文本进行预处理,如去除停用词、词形还原等。 ### 2...
Lucene提供了一系列预定义的分析器,如StandardAnalyzer,针对英文文本进行了特殊优化,同时支持自定义分析器以适应各种语言和应用场景。 2. 文档(Document):在Lucene中,每个文档对应一个Document对象,用于...
1. **索引**:Lucene首先对文本进行索引,将文本内容转换为一系列可搜索的结构。索引过程包括分词(Tokenization)、词干提取(Stemming)、停用词处理(Stop Word Removal)等步骤。 2. **文档(Document)**:在...
将文档分解成一系列的词项。 - **第三步:语言处理**。这一步骤包括去除停用词、词干提取等操作。 - **第四步:创建索引**。将处理后的词项和相关信息添加到索引中。 - **1. 创建字典**:收集所有词项并确保其唯一...
- **分析器(Analyzer)**: 分析器负责将输入文本分解成一系列的关键词(Token),进行词化、过滤等操作,以适应索引和搜索的需求。 **2. Lucene的主要操作流程** 1. **创建索引(Indexing)**: 首先,读取文档...