学习的资料是 lucene 4.10 版本,比较沉旧,查阅最新的 lucene 版本 6.6 的官方文档,整理出如下几个使用中的不一样。
从浅入深依次为 (注:不是根据版本前后)html
下面,就让我详细的整理出不一样。算法
如下是 IndexWriterConfig 4.10 的源码部分spring
public IndexWriterConfig(Version matchVersion, Analyzer analyzer) { super(analyzer, matchVersion); } //这里的version 通常要写为 Version 类中 public static final Version LATEST;
而 IndexWriterConfig 6.6 中apache
//无参构造方法 public IndexWriterConfig() { this(new StandardAnalyzer()); } //有参构造方法 public IndexWriterConfig(Analyzer analyzer) { super(analyzer); this.writer = new SetOnce(); }
能够看出,在 6.6 版本中 version 再也不是必要的,而且,存在无参构造方法,能够直接使用默认的 StandardAnalyzer 分词器。api
正常建立 Directory 类的方法以下安全
Directory di = FSdirectory.open();
如下是 IndexWriterConfig 4.10 的源码部分mvc
public static FSDirectory open(File path) throws IOException { return open(path, (LockFactory)null); }
这里能够看出 open 方法 用的参数类型 为Fileless
而 IndexWriterConfig 6.6 中ide
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()
根据 官方的 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?
PointValues 取代了NumericField
由于PointValues 更快,更小,更便于资源的利用。因此,全部的 legacy**都被取代了。
代码的话,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, ...);
还要注意的是:
若是要排序使用,必须同时建立同名的StoredField类与NumericDocValuesField类
例:
doc.add(new NumericDocValuesField("price",price)); doc.add(new IntPoint("price",price)); doc.add(new StoredField("price",price));
根据 官方的 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); } }
经过用静态内部类实例化自身的方法,增强了类自身的稳定性与安全性。避免可能发生的小意外,而致使代码出现问题的可能性
下面给出代码,能够更好的看出差异
//原先的 使用方法 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();
在 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 后,发现了几个与之相关的 类
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);
具体方法还不清楚,但愿知道的大神能够给我解答
另外,还有两个便于操做的类:
源码以下:
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");
请看 下篇 文章。