學習的資料是 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");
請看 下篇 文章。