文档章节

lucene6.6 学习心得

柳初心
 柳初心
发布于 2017/07/21 13:27
字数 1809
阅读 88
收藏 0

##前言 学习的资料是 lucene 4.10 版本,比较沉旧,查阅最新的 lucene 版本 6.6 的官方文档,整理出以下几个使用中的不同。
从浅入深依次为 (注:不是根据版本先后)

  1. IndexWriterConfig 的构造方法
  2. Directory 的生成方法 FSDirectory.open()
  3. legacyXXField 与legacyNumericRangeQuery 的废弃
  4. BooleanQuery() 方法的改变
  5. setBoost()方法的废除    
    
  6. 中文分词器的改进
    

下面,就让我详细的整理出不同。

1.IndexWriterConfig

以下是 IndexWriterConfig 4.10 的源码部分

    public IndexWriterConfig(Version matchVersion, Analyzer analyzer) {
        super(analyzer, matchVersion);
    }
    //这里的version 一般要写为     
    Version 类中
    public static final Version LATEST;

而 IndexWriterConfig 6.6 中

    //无参构造方法 
    public IndexWriterConfig() {
        this(new StandardAnalyzer());
    }
    //有参构造方法
    public IndexWriterConfig(Analyzer analyzer) {
        super(analyzer);
        this.writer = new SetOnce();
    }

可以看出,在 6.6 版本中 version 不再是必要的,并且,存在无参构造方法,可以直接使用默认的 StandardAnalyzer 分词器。

2.Directory

正常创建 Directory 类的方法如下

Directory di = FSdirectory.open();

以下是 IndexWriterConfig 4.10 的源码部分

    public static FSDirectory open(File path) throws IOException {
        return open(path, (LockFactory)null);
    }

这里可以看出 open 方法 用的参数类型 为File

而 IndexWriterConfig 6.6 中

    public static FSDirectory open(Path path) throws IOException {
        return open(path, FSLockFactory.getDefault());
    }

open 方法使用了 Path 类,这个类是 NIO 中的类,可以提高查询的效率。
由 File 转化为 Path 的 方法 --->

File file = new File (absolutePath);
Path path = file.toPath()

3.legacyXXField 与legacyNumericRangeQuery

###1. 分析 根据 官方的 Migration Guide 中的说法

PointValues replaces NumericField (LUCENE-6917)

PointValues provides faster indexing and searching, a smaller index size, and less heap used at search time. See org.apache.lucene.index.PointValues for an introduction.

Legacy numeric encodings from previous versions of Lucene are deprecated as LegacyIntField, LegacyFloatField, LegacyLongField, and LegacyDoubleField, and can be searched with LegacyNumericRangeQuery.

以及开发者的测试

DimensionalValues seems to be better across the board (indexing time, indexing size, search-speed, search-time heap required) than NumericField, at least in my testing so far.
I think for 6.0 we should move IntField, LongField, FloatField, DoubleField and NumericRangeQuery to backward-codecs, and rename with Legacy prefix?

###2.结论

PointValues 取代了NumericField 因为PointValues 更快,更小,更便于资源的利用。所以,所有的 legacy**都被取代了。

###3.代码对比 代码的话,lucene 的官方文档给了一个简单的例子

   // add year 1970 to document
   document.add(new IntPoint("year", 1970));
   // index document
   writer.addDocument(document);
   ...
   // issue range query of 1960-1980
   Query query = IntPoint.newRangeQuery("year", 1960, 1980);
   TopDocs docs = searcher.search(query, ...);

另外我自己写了一个 已经**@Deprecated**的方法 与上面 进行对比

      // add year 1970 to document
   document.add(new IntField("year", 1970));
   // index document
   writer.addDocument(document);
   ...
   // issue range query of 1960-1980
   Query query = new NumericRangeQuery("year", 1960, 1980,false,false);
   TopDocs docs = searcher.search(query, ...);

还要注意的是:

  1. 如果要存储,必须创建同名的StoredField类
  2. 如果要排序使用,必须同时创建同名的StoredField类与NumericDocValuesField类 例:
doc.add(new NumericDocValuesField("price",price));  
doc.add(new IntPoint("price",price));  
doc.add(new StoredField("price",price));

4.BooleanQuery() 的构造方法改变

###1.分析 根据 官方的 Migration Guide 中的说法

PhraseQuery, MultiPhraseQuery, and BooleanQuery made immutable (LUCENE-6531 LUCENE-7064 LUCENE-6570)
也就是说, BooleanQuery这个类 一旦建立就不能再改变了。

从源码中我们可以更好的看出改变 lucene 4.10 的源码里 BooleanQuery 的类 主要方法如下

    /* 构造器*/
    public BooleanQuery() {
        this.disableCoord = false;
    }
    public BooleanQuery(boolean disableCoord) {
        this.disableCoord = disableCoord;
    }
    /*主要方法*/
    public void add(BooleanClause clause) {
        if(this.clauses.size() >= maxClauseCount) {
            throw new BooleanQuery.TooManyClauses();
        } else {
            this.clauses.add(clause);
        }
    }

lucene 6.6 的源码里, BooleanQuery 的主要方法如下:

private BooleanQuery(boolean disableCoord, int minimumNumberShouldMatch, BooleanClause[] clauses) 

可以看出 , BooleanQuery 的构造器的范围是** private **的,只能在类的内部调用。
并且最大的改变是多出了静态内部类 Builder
以下是 Builder 的部分源码

    public static class Builder {
        private boolean disableCoord;
        private int minimumNumberShouldMatch;
        private final List<BooleanClause> clauses = new ArrayList();
        /* 无参构造器 */
        // 相当于 BooleanQuery 的 构造器
        public Builder() {
        }
        //相当于 BooleanQuery 的 add 方法
        public BooleanQuery.Builder add(Query query, Occur occur) {
            return this.add(new BooleanClause(query, occur));
        }
        //返回值是 BooleanQuery, 构造一个BooleanQuery 类。
        public BooleanQuery build() {
            return new BooleanQuery(this.disableCoord, this.minimumNumberShouldMatch, (BooleanClause[])this.clauses.toArray(new BooleanClause[0]), null);
        }
    }

###2.结论 通过用静态内部类实例化自身的方法,加强了类自身的稳定性与安全性。避免可能发生的小意外,而导致代码出现问题的可能性

###3.代码对比 下面给出代码,可以更好的看出差别

//原先的 使用方法
BooleanQuery bq = new BooleanQuery();     
bq.add(q1, Occur.SHOULD);     
bq.add(q2, Occur.SHOULD); bq.add(q3, Occur.MUST); 

//现在的 使用方法
BooleanQuery bq = new BooleanQuery.Builder()
                                     .add(q1, Occur.SHOULD)    
                                     .add(q2, Occur.SHOULD)
                                     .add(q3, Occur.SHOULD)
                                     .build();

##5. seBoost()方法的废除 在 lucene 4.10 包中, setBoost方法被用于 相关度 的排序中。改变创建索引时的 Boost -- 权值。根据一系列计算方法 (旧版采用的 空间向量模型算法),最终得出其打分。 代码如下 :

Field fi1 = new Field("id" , 1, STORE.YES);
// Boost 值默认为 1.0f 
fi1.setBoost(100f)
Document do = new Document();
do.add(fi1);

而在新版 lucene 6.6 中, setBoost 方法被 废除
根据lucene 的官方文档中的说法

org.apache.lucene.document.Field.setBoost(float)
Index-time boosts are deprecated, please index index-time scoring factors into a doc value field and combine them with the score at query time using eg. FunctionScoreQuery.

中文翻译后:
索引时权值被废除,请将索引时打分因素添加入field域中,然后在查询时,使用功能性打分查询语句,进行关联查询。

我在查看了 大部分关联的 api 后,发现了几个与之相关的 类

  1. BoostAttribute
  2. termsEnum
  3. MultiQuery

lucene 的官方文档中对 BoostAttribute 的描述是这样的。
BoostAttribute --- >
Add this Attribute to a TermsEnum returned by MultiTermQuery.getTermsEnum(Terms,AttributeSource) and update the boost on each returned term.
方法描述如下

protected abstract TermsEnum getTermsEnum(Terms terms,AttributeSource atts)	
//Construct the enumeration to be used, expanding the pattern term.
//很明显,这是个抽象方法,必须由子类实现

**BoostAttribute **是个接口,其实现类 BoostAttributeImpl 中源码如下

    public BoostAttributeImpl() {
    }
    public void setBoost(float boost) {
        this.boost = boost;
    }

推测使用如下 --- 以下是伪代码

//设置 Boost 属性
BoostAttribute ba = new BoostAttributeImpl();
ba.setBoost(100f);
//设置 Query 的实现类
Query query =  new MultiTermqueryChildren(new Terms());
TermEnum te = query.getTermsEnum(Terms,ba);

具体方法还不清楚,希望知道的大神可以给我解答

另外,还有两个便于操作的类:

  1. BoostQuery
  2. MultiFieldQueryParser

1.BoostQuery

源码如下:

    public BoostQuery(Query query, float boost) {
        this.query = (Query)Objects.requireNonNull(query);
        this.boost = boost;
    }

分析:
相当于一个包装类,将 Query 设置 Boost 值 ,然后包装起来。
再通过复合查询语句,可以突出 Query 的优先级。

使用如下:

//查询 索引域 中的 file_name , file_content
Query q1 = new TermQuery(new Term(“file_name” ,”springmvc.txt”);
Query q2 = new TermQuery(new Term(“file_content”,”springmvc.txt”);
//将 q1 设置 Boost 值 
BoostQuery q3 = new BoostQuery(q1,100f);
//复合语句查询
BooleanQuery.Builder() builder = new new BooleanQuery.Builder();
builder.add(q3, Occur.MUST)
builder.add(q2, Occur.MUST)
//由于 file_name 的查询语句经过 BoostQuery 的包装
//因此 file_name 的优先级更高。
BooleanQuery query = builder.build();

2.MultiFieldQueryParser 和原先版本相同 , 就不阐述源码,直接上使用方法
使用如下 :

//设置组合查询域
String[] fields = {"file_name","file_content"};

//设置评分,文件名称中包括关键字的评分高
Map<String,Float> boosts = new HashMap<String,Float>();
boosts.put("file_name", 10.0f);

//创建查询解析器
QueryParser queryParser =  new MultiFieldQueryParser(fields, new IKAnalyzer(), boosts);
//查询文件名、文件内容中包括“springmvc.txt”关键字的文档,由于设置了文件名称域的加权值高,所以名称中匹配到关键字的应该排在前边
Query query = queryParser.parse("springmvc.txt");

###6. 中文分词器 -- iKAnalyzer 的 lucene 6.6 适配

请看 下篇 文章。

© 著作权归作者所有

共有 人打赏支持
柳初心
粉丝 0
博文 31
码字总数 15977
作品 0
南昌
Lucene6.6 添加因子影响文档打分

需求描述: 我想添加一个可以改变文档打分的因素,以便可以灵活调整搜索结果。 注:在Lucene6.6 版本的上 Document.setBoost 方法已经被删除。 通过阅读 文档 和 Lucene原理和代码解析(这是早...

叶大侠
05/03
0
0
MapXtreme 2005 GIS开发入门系列 索引

前言: 今天没写什么文章,刚回到家本来是要用 CYQ.Data 框架 继续重构以前的博客系列项目,回头看见博客有MapXtreme的留言; 就顺手花了2小时左右,把以前写的十四篇MapXtreme文章重新编辑了...

晨曦之光
2012/03/09
0
0
我从吴恩达深度学习课程中学到的21个心得:加拿大银行首席分析师“学霸“笔记分享

大数据文摘作品 编译:新知之路、小饭盆、钱天培 今年8月,吴恩达的深度学习课程正式上线,并即刻吸引了众多深度学习粉丝的“顶礼膜拜”。一如吴恩达此前在Coursera上的机器学习课程,这几门...

dzjx2eotaa24adr
2017/12/07
0
0
我从吴恩达深度学习课程中学到的21个心得

     大数据文摘作品   编译:新知之路、小饭盆、钱天培   今年8月,吴恩达的深度学习课程正式上线,并即刻吸引了众多深度学习粉丝的“顶礼膜拜”。一如吴恩达此前在Coursera上的机器...

大数据文摘
2017/12/07
0
0
Common Lisp 的一点学习心得==选择一种实现,然后好好看它的描述文档,多练习,多提问

Common Lisp 的一点学习心得==选择一种实现,然后好好看它的描述文档,多练习,多提问 真正接触 Common Lisp 也有一段时间了,对 Common Lisp 的一点心得就是:明确地确定一种实现,然后以这...

FreeBlues
2013/04/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java的快速失败和安全失败

一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。 原理:迭代器在...

狼王黄师傅
14分钟前
5
0
Echarts X轴Y轴配置参数详情

mytextStyle={ color:"#333", //文字颜色 fontStyle:"normal", //italic斜体 oblique倾斜 fontWeight:"normal", //文字粗细bold bolder lighter 100 | 200 | 300 | 400... fontFamily:"sans......

wqzbxh
16分钟前
1
0
解决kettle使用JDBC读取Oracle速度慢的问题

jdbc连接添加如下信息: defaultRowPrefetch=20000

了凡川
20分钟前
1
0
Linux学习-1015

8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下 相关测验题目:题目:http://ask.apelearn.com/question/5437 扩展 扩展 1. source exec 区别...

wxy丶
21分钟前
2
0
Spring Boot核心注解讲解

Spring Boot核心注解讲解 Spring Boot最大的特点是无需XML配置文件,能自动扫描包路径装载并注入对象,并能做到根据classpath下的jar包自动配置。 所以Spring Boot最核心的3个注解就是: 1,...

DemonsI
28分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部