Lucene5学习之排序-Sort

简介:

  这回我们来学习Lucene的排序。机智的少年应该已经发现了,IndexSearcher类的search方法有好几个重载:

      

Java代码   收藏代码
  1. /** Finds the top <code>n</code> 
  2.    * hits for <code>query</code>. 
  3.    * 
  4.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  5.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  6.    */  
  7.   public TopDocs search(Query query, int n)  
  8.     throws IOException {  
  9.     return search(query, null, n);  
  10.   }  
  11.   
  12.   
  13.   /** Finds the top <code>n</code> 
  14.    * hits for <code>query</code>, applying <code>filter</code> if non-null. 
  15.    * 
  16.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  17.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  18.    */  
  19.   public TopDocs search(Query query, Filter filter, int n)  
  20.     throws IOException {  
  21.     return search(createNormalizedWeight(wrapFilter(query, filter)), null, n);  
  22.   }  
  23.   
  24.   /** Lower-level search API. 
  25.    * 
  26.    * <p>{@link LeafCollector#collect(int)} is called for every matching 
  27.    * document. 
  28.    * 
  29.    * @param query to match documents 
  30.    * @param filter if non-null, used to permit documents to be collected. 
  31.    * @param results to receive hits 
  32.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  33.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  34.    */  
  35.   public void search(Query query, Filter filter, Collector results)  
  36.     throws IOException {  
  37.     search(leafContexts, createNormalizedWeight(wrapFilter(query, filter)), results);  
  38.   }  
  39.   
  40.   /** Lower-level search API. 
  41.    * 
  42.    * <p>{@link LeafCollector#collect(int)} is called for every matching document. 
  43.    * 
  44.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  45.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  46.    */  
  47.   public void search(Query query, Collector results)  
  48.     throws IOException {  
  49.     search(leafContexts, createNormalizedWeight(query), results);  
  50.   }  
  51.     
  52.   /** Search implementation with arbitrary sorting.  Finds 
  53.    * the top <code>n</code> hits for <code>query</code>, applying 
  54.    * <code>filter</code> if non-null, and sorting the hits by the criteria in 
  55.    * <code>sort</code>. 
  56.    *  
  57.    * <p>NOTE: this does not compute scores by default; use 
  58.    * {@link IndexSearcher#search(Query,Filter,int,Sort,boolean,boolean)} to 
  59.    * control scoring. 
  60.    * 
  61.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  62.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  63.    */  
  64.   public TopFieldDocs search(Query query, Filter filter, int n,  
  65.                              Sort sort) throws IOException {  
  66.     return search(createNormalizedWeight(wrapFilter(query, filter)), n, sort, falsefalse);  
  67.   }  
  68.   
  69.   /** Search implementation with arbitrary sorting, plus 
  70.    * control over whether hit scores and max score 
  71.    * should be computed.  Finds 
  72.    * the top <code>n</code> hits for <code>query</code>, applying 
  73.    * <code>filter</code> if non-null, and sorting the hits by the criteria in 
  74.    * <code>sort</code>.  If <code>doDocScores</code> is <code>true</code> 
  75.    * then the score of each hit will be computed and 
  76.    * returned.  If <code>doMaxScore</code> is 
  77.    * <code>true</code> then the maximum score over all 
  78.    * collected hits will be computed. 
  79.    *  
  80.    * @throws BooleanQuery.TooManyClauses If a query would exceed  
  81.    *         {@link BooleanQuery#getMaxClauseCount()} clauses. 
  82.    */  
  83.   public TopFieldDocs search(Query query, Filter filter, int n,  
  84.                              Sort sort, boolean doDocScores, boolean doMaxScore) throws IOException {  
  85.     return search(createNormalizedWeight(wrapFilter(query, filter)), n, sort, doDocScores, doMaxScore);  
  86.   }  

   query参数就不用解释了,filter用来再次过滤的,int n表示只返回Top N,Sort表示排序对象,

  doDocScores这个参数是重点,表示是否对文档进行相关性打分,如果你设为false,那你索引文档的score值就是NAN,

   doMaxScore表示啥意思呢,举个例子说明吧,假如你有两个Query(QueryA和QueryB),两个条件是通过BooleanQuery连接起来的,假如QueryA条件匹配到某个索引文档,而QueryB条件也同样匹配到该文档,如果doMaxScore设为true,表示该文档的评分计算规则为取两个Query(当然你可能会有N个Query链接,那就是N个Query中取最大值)之中的最大值,否则就是取两个Query查询评分的相加求和。默认为false.

   注意:在Lucene4.x时代,doDocScores和doMaxScore这两个参数可以通过indexSearcher类来设置,比如这样:

Java代码   收藏代码
  1. searcher.setDefaultFieldSortScoring(truefalse);  

   而在Lucene5.x时代,你只能在调用search方法时传入这两个参数,比如这样:

Java代码   收藏代码
  1. searcher.search(query, filter, n, sort, doDocScores, doMaxScore);  

 

   看方法声明我们知道,我们如果需要改变默认的按评分降序排序行为,则必须传入一个Sort对象,那我们来观摩下Sort类源码:

    

Java代码   收藏代码
  1. package org.apache.lucene.search;  
  2.   
  3. /* 
  4.  * Licensed to the Apache Software Foundation (ASF) under one or more 
  5.  * contributor license agreements.  See the NOTICE file distributed with 
  6.  * this work for additional information regarding copyright ownership. 
  7.  * The ASF licenses this file to You under the Apache License, Version 2.0 
  8.  * (the "License"); you may not use this file except in compliance with 
  9.  * the License.  You may obtain a copy of the License at 
  10.  * 
  11.  *     http://www.apache.org/licenses/LICENSE-2.0 
  12.  * 
  13.  * Unless required by applicable law or agreed to in writing, software 
  14.  * distributed under the License is distributed on an "AS IS" BASIS, 
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  16.  * See the License for the specific language governing permissions and 
  17.  * limitations under the License. 
  18.  */  
  19.   
  20. import java.io.IOException;  
  21. import java.util.Arrays;  
  22.   
  23.   
  24. /** 
  25.  * Encapsulates sort criteria for returned hits. 
  26.  * 
  27.  * <p>The fields used to determine sort order must be carefully chosen. 
  28.  * Documents must contain a single term in such a field, 
  29.  * and the value of the term should indicate the document's relative position in 
  30.  * a given sort order.  The field must be indexed, but should not be tokenized, 
  31.  * and does not need to be stored (unless you happen to want it back with the 
  32.  * rest of your document data).  In other words: 
  33.  * 
  34.  * <p><code>document.add (new Field ("byNumber", Integer.toString(x), Field.Store.NO, Field.Index.NOT_ANALYZED));</code></p> 
  35.  *  
  36.  * 
  37.  * <p><h3>Valid Types of Values</h3> 
  38.  * 
  39.  * <p>There are four possible kinds of term values which may be put into 
  40.  * sorting fields: Integers, Longs, Floats, or Strings.  Unless 
  41.  * {@link SortField SortField} objects are specified, the type of value 
  42.  * in the field is determined by parsing the first term in the field. 
  43.  * 
  44.  * <p>Integer term values should contain only digits and an optional 
  45.  * preceding negative sign.  Values must be base 10 and in the range 
  46.  * <code>Integer.MIN_VALUE</code> and <code>Integer.MAX_VALUE</code> inclusive. 
  47.  * Documents which should appear first in the sort 
  48.  * should have low value integers, later documents high values 
  49.  * (i.e. the documents should be numbered <code>1..n</code> where 
  50.  * <code>1</code> is the first and <code>n</code> the last). 
  51.  * 
  52.  * <p>Long term values should contain only digits and an optional 
  53.  * preceding negative sign.  Values must be base 10 and in the range 
  54.  * <code>Long.MIN_VALUE</code> and <code>Long.MAX_VALUE</code> inclusive. 
  55.  * Documents which should appear first in the sort 
  56.  * should have low value integers, later documents high values. 
  57.  *  
  58.  * <p>Float term values should conform to values accepted by 
  59.  * {@link Float Float.valueOf(String)} (except that <code>NaN</code> 
  60.  * and <code>Infinity</code> are not supported). 
  61.  * Documents which should appear first in the sort 
  62.  * should have low values, later documents high values. 
  63.  * 
  64.  * <p>String term values can contain any valid String, but should 
  65.  * not be tokenized.  The values are sorted according to their 
  66.  * {@link Comparable natural order}.  Note that using this type 
  67.  * of term value has higher memory requirements than the other 
  68.  * two types. 
  69.  * 
  70.  * <p><h3>Object Reuse</h3> 
  71.  * 
  72.  * <p>One of these objects can be 
  73.  * used multiple times and the sort order changed between usages. 
  74.  * 
  75.  * <p>This class is thread safe. 
  76.  * 
  77.  * <p><h3>Memory Usage</h3> 
  78.  * 
  79.  * <p>Sorting uses of caches of term values maintained by the 
  80.  * internal HitQueue(s).  The cache is static and contains an integer 
  81.  * or float array of length <code>IndexReader.maxDoc()</code> for each field 
  82.  * name for which a sort is performed.  In other words, the size of the 
  83.  * cache in bytes is: 
  84.  * 
  85.  * <p><code>4 * IndexReader.maxDoc() * (# of different fields actually used to sort)</code> 
  86.  * 
  87.  * <p>For String fields, the cache is larger: in addition to the 
  88.  * above array, the value of every term in the field is kept in memory. 
  89.  * If there are many unique terms in the field, this could 
  90.  * be quite large. 
  91.  * 
  92.  * <p>Note that the size of the cache is not affected by how many 
  93.  * fields are in the index and <i>might</i> be used to sort - only by 
  94.  * the ones actually used to sort a result set. 
  95.  * 
  96.  * <p>Created: Feb 12, 2004 10:53:57 AM 
  97.  * 
  98.  * @since   lucene 1.4 
  99.  */  
  100. public class Sort {  
  101.   
  102.   /** 
  103.    * Represents sorting by computed relevance. Using this sort criteria returns 
  104.    * the same results as calling 
  105.    * {@link IndexSearcher#search(Query,int) IndexSearcher#search()}without a sort criteria, 
  106.    * only with slightly more overhead. 
  107.    */  
  108.   public static final Sort RELEVANCE = new Sort();  
  109.   
  110.   /** Represents sorting by index order. */  
  111.   public static final Sort INDEXORDER = new Sort(SortField.FIELD_DOC);  
  112.   
  113.   // internal representation of the sort criteria  
  114.   SortField[] fields;  
  115.   
  116.   /** 
  117.    * Sorts by computed relevance. This is the same sort criteria as calling 
  118.    * {@link IndexSearcher#search(Query,int) IndexSearcher#search()}without a sort criteria, 
  119.    * only with slightly more overhead. 
  120.    */  
  121.   public Sort() {  
  122.     this(SortField.FIELD_SCORE);  
  123.   }  
  124.   
  125.   /** Sorts by the criteria in the given SortField. */  
  126.   public Sort(SortField field) {  
  127.     setSort(field);  
  128.   }  
  129.   
  130.   /** Sets the sort to the given criteria in succession: the 
  131.    *  first SortField is checked first, but if it produces a 
  132.    *  tie, then the second SortField is used to break the tie, 
  133.    *  etc.  Finally, if there is still a tie after all SortFields 
  134.    *  are checked, the internal Lucene docid is used to break it. */  
  135.   public Sort(SortField... fields) {  
  136.     setSort(fields);  
  137.   }  
  138.   
  139.   /** Sets the sort to the given criteria. */  
  140.   public void setSort(SortField field) {  
  141.     this.fields = new SortField[] { field };  
  142.   }  
  143.   
  144.   /** Sets the sort to the given criteria in succession: the 
  145.    *  first SortField is checked first, but if it produces a 
  146.    *  tie, then the second SortField is used to break the tie, 
  147.    *  etc.  Finally, if there is still a tie after all SortFields 
  148.    *  are checked, the internal Lucene docid is used to break it. */  
  149.   public void setSort(SortField... fields) {  
  150.     this.fields = fields;  
  151.   }  
  152.     
  153.   /** 
  154.    * Representation of the sort criteria. 
  155.    * @return Array of SortField objects used in this sort criteria 
  156.    */  
  157.   public SortField[] getSort() {  
  158.     return fields;  
  159.   }  
  160.   
  161.   /** 
  162.    * Rewrites the SortFields in this Sort, returning a new Sort if any of the fields 
  163.    * changes during their rewriting. 
  164.    * 
  165.    * @param searcher IndexSearcher to use in the rewriting 
  166.    * @return {@code this} if the Sort/Fields have not changed, or a new Sort if there 
  167.    *        is a change 
  168.    * @throws IOException Can be thrown by the rewriting 
  169.    * @lucene.experimental 
  170.    */  
  171.   public Sort rewrite(IndexSearcher searcher) throws IOException {  
  172.     boolean changed = false;  
  173.       
  174.     SortField[] rewrittenSortFields = new SortField[fields.length];  
  175.     for (int i = 0; i < fields.length; i++) {  
  176.       rewrittenSortFields[i] = fields[i].rewrite(searcher);  
  177.       if (fields[i] != rewrittenSortFields[i]) {  
  178.         changed = true;  
  179.       }  
  180.     }  
  181.   
  182.     return (changed) ? new Sort(rewrittenSortFields) : this;  
  183.   }  
  184.   
  185.   @Override  
  186.   public String toString() {  
  187.     StringBuilder buffer = new StringBuilder();  
  188.   
  189.     for (int i = 0; i < fields.length; i++) {  
  190.       buffer.append(fields[i].toString());  
  191.       if ((i+1) < fields.length)  
  192.         buffer.append(',');  
  193.     }  
  194.   
  195.     return buffer.toString();  
  196.   }  
  197.   
  198.   /** Returns true if <code>o</code> is equal to this. */  
  199.   @Override  
  200.   public boolean equals(Object o) {  
  201.     if (this == o) return true;  
  202.     if (!(o instanceof Sort)) return false;  
  203.     final Sort other = (Sort)o;  
  204.     return Arrays.equals(this.fields, other.fields);  
  205.   }  
  206.   
  207.   /** Returns a hash code value for this object. */  
  208.   @Override  
  209.   public int hashCode() {  
  210.     return 0x45aaf665 + Arrays.hashCode(fields);  
  211.   }  
  212.   
  213.   /** Returns true if the relevance score is needed to sort documents. */  
  214.   public boolean needsScores() {  
  215.     for (SortField sortField : fields) {  
  216.       if (sortField.needsScores()) {  
  217.         return true;  
  218.       }  
  219.     }  
  220.     return false;  
  221.   }  
  222.   
  223. }  

    首先定义了两个静态常量:

   public static final Sort RELEVANCE = new Sort();

   public static final Sort INDEXORDER = new Sort(SortField.FIELD_DOC);

   RELEVANCE 表示按评分排序,

   INDEXORDER 表示按文档索引排序,什么叫按文档索引排序?意思是按照索引文档的docId排序,我们在创建索引文档的时候,Lucene默认会帮我们自动加一个Field(docId),如果你没有修改默认的排序行为,默认是先按照索引文档相关性评分降序排序(如果你开启了对索引文档打分功能的话),然后如果两个文档评分相同,再按照索引文档id升序排列。

   然后就是Sort的构造函数,你需要提供一个SortField对象,其中有一个构造函数要引起你们的注意:

Java代码   收藏代码
  1. public Sort(SortField... fields) {  
  2.     setSort(fields);  
  3.   }  

 SortField... fields写法是JDK7引入的新语法,类似于以前的SortField[] fields写法,但它又于以前的这种写法有点不同,它支持field1,field2,field3,field4,field5,.........fieldN这种方式传参,当然你也可以传入一个数组也是可以的。其实我是想说Sort支持传入多个SortField即表示Sort是支持按多个域进行排序,就像SQL里的order by age,id,哦-哦,TM又扯远了,那接着去观摩下SoreField的源码,看看究竟:

Java代码   收藏代码
  1. public class SortField {  
  2.   
  3.   /** 
  4.    * Specifies the type of the terms to be sorted, or special types such as CUSTOM 
  5.    */  
  6.   public static enum Type {  
  7.   
  8.     /** Sort by document score (relevance).  Sort values are Float and higher 
  9.      * values are at the front. */  
  10.     SCORE,  
  11.   
  12.     /** Sort by document number (index order).  Sort values are Integer and lower 
  13.      * values are at the front. */  
  14.     DOC,  
  15.   
  16.     /** Sort using term values as Strings.  Sort values are String and lower 
  17.      * values are at the front. */  
  18.     STRING,  
  19.   
  20.     /** Sort using term values as encoded Integers.  Sort values are Integer and 
  21.      * lower values are at the front. */  
  22.     INT,  
  23.   
  24.     /** Sort using term values as encoded Floats.  Sort values are Float and 
  25.      * lower values are at the front. */  
  26.     FLOAT,  
  27.   
  28.     /** Sort using term values as encoded Longs.  Sort values are Long and 
  29.      * lower values are at the front. */  
  30.     LONG,  
  31.   
  32.     /** Sort using term values as encoded Doubles.  Sort values are Double and 
  33.      * lower values are at the front. */  
  34.     DOUBLE,  
  35.   
  36.     /** Sort using a custom Comparator.  Sort values are any Comparable and 
  37.      * sorting is done according to natural order. */  
  38.     CUSTOM,  
  39.   
  40.     /** Sort using term values as Strings, but comparing by 
  41.      * value (using String.compareTo) for all comparisons. 
  42.      * This is typically slower than {@link #STRING}, which 
  43.      * uses ordinals to do the sorting. */  
  44.     STRING_VAL,  
  45.   
  46.     /** Sort use byte[] index values. */  
  47.     BYTES,  
  48.   
  49.     /** Force rewriting of SortField using {@link SortField#rewrite(IndexSearcher)} 
  50.      * before it can be used for sorting */  
  51.     REWRITEABLE  
  52.   }  
  53.   
  54.   /** Represents sorting by document score (relevance). */  
  55.   public static final SortField FIELD_SCORE = new SortField(null, Type.SCORE);  
  56.   
  57.   /** Represents sorting by document number (index order). */  
  58.   public static final SortField FIELD_DOC = new SortField(null, Type.DOC);  
  59.   
  60.   private String field;  
  61.   private Type type;  // defaults to determining type dynamically  
  62.   boolean reverse = false;  // defaults to natural order  
  63.   
  64.   // Used for CUSTOM sort  
  65.   private FieldComparatorSource comparatorSource;  

 首先你看到的里面定义了一个排序规则类型的枚举Type,

   SCORE:表示按评分排序,默认是降序

   DOC:按文档ID排序,除了评分默认是降序以外,其他默认都是升序

   STRING:表示把域的值转成字符串进行排序,

   STRING_VAL也是把域的值转成字符串进行排序,不过比较的时候是调用String.compareTo来比较的

   STRING_VAL性能比STRING要差,STRING是怎么比较的,源码里没有说明。

   相应的还有INT,FLOAT,DOUBLE,LONG就不多说了,

  CUSTOM:表示自定义排序,这个是要结合下面的成员变量

   private FieldComparatorSource comparatorSource;一起使用,即指定一个自己的自定义的比较器,通过自己的比较器来决定排序顺序。

   SortField还有3个比较重要的成员变量,除了刚才的说自定义比较器外:

Java代码   收藏代码
  1. private String field;  
  2. private Type type;  // defaults to determining type dynamically  
  3. boolean reverse = false;  // defaults to natural order  

 毫无疑问,Field表示你要对哪个域进行排序,即排序域名称

Type即上面解释过的排序规则即按什么来排序,评分 or docID 等等

reverse表示是否反转默认的排序行为,即升序变降序,降序就变升序,比如默认评分是降序的,reverse设为true,则默认评分就按升序排序了,而其他域就按升序排序了。默认reverse为false.

OK,了解以上内容,我想大家已经对如何实现自己对索引文档的自定义排序已经了然于胸了。下面我把我写的测试demo代码贴出来供大家参考:

   首先创建用于测试的索引文档:

   

Java代码   收藏代码
  1. package com.yida.framework.lucene5.sort;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.nio.file.Paths;  
  7. import java.text.ParseException;  
  8. import java.util.ArrayList;  
  9. import java.util.Date;  
  10. import java.util.List;  
  11. import java.util.Properties;  
  12.   
  13. import org.apache.lucene.analysis.Analyzer;  
  14. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  15. import org.apache.lucene.document.DateTools;  
  16. import org.apache.lucene.document.Document;  
  17. import org.apache.lucene.document.Field;  
  18. import org.apache.lucene.document.IntField;  
  19. import org.apache.lucene.document.NumericDocValuesField;  
  20. import org.apache.lucene.document.SortedDocValuesField;  
  21. import org.apache.lucene.document.SortedNumericDocValuesField;  
  22. import org.apache.lucene.document.StringField;  
  23. import org.apache.lucene.document.TextField;  
  24. import org.apache.lucene.index.IndexWriter;  
  25. import org.apache.lucene.index.IndexWriterConfig;  
  26. import org.apache.lucene.index.IndexWriterConfig.OpenMode;  
  27. import org.apache.lucene.store.Directory;  
  28. import org.apache.lucene.store.FSDirectory;  
  29. import org.apache.lucene.util.BytesRef;  
  30. /** 
  31.  * 创建测试索引 
  32.  * @author Lanxiaowei 
  33.  * 
  34.  */  
  35. public class CreateTestIndex {  
  36.     public static void main(String[] args) throws IOException {  
  37.         String dataDir = "C:/data";  
  38.         String indexDir = "C:/lucenedir";  
  39.   
  40.         Directory dir = FSDirectory.open(Paths.get(indexDir));  
  41.         Analyzer analyzer = new StandardAnalyzer();  
  42.         IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);  
  43.         indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);  
  44.         IndexWriter writer = new IndexWriter(dir, indexWriterConfig);  
  45.   
  46.         List<File> results = new ArrayList<File>();  
  47.         findFiles(results, new File(dataDir));  
  48.         System.out.println(results.size() + " books to index");  
  49.   
  50.         for (File file : results) {  
  51.             Document doc = getDocument(dataDir, file);  
  52.             writer.addDocument(doc);  
  53.         }  
  54.         writer.close();  
  55.         dir.close();  
  56.   
  57.     }  
  58.   
  59.     /** 
  60.      * 查找指定目录下的所有properties文件 
  61.      *  
  62.      * @param result 
  63.      * @param dir 
  64.      */  
  65.     private static void findFiles(List<File> result, File dir) {  
  66.         for (File file : dir.listFiles()) {  
  67.             if (file.getName().endsWith(".properties")) {  
  68.                 result.add(file);  
  69.             } else if (file.isDirectory()) {  
  70.                 findFiles(result, file);  
  71.             }  
  72.         }  
  73.     }  
  74.   
  75.     /** 
  76.      * 读取properties文件生成Document 
  77.      *  
  78.      * @param rootDir 
  79.      * @param file 
  80.      * @return 
  81.      * @throws IOException 
  82.      */  
  83.     public static Document getDocument(String rootDir, File file)  
  84.             throws IOException {  
  85.         Properties props = new Properties();  
  86.         props.load(new FileInputStream(file));  
  87.   
  88.         Document doc = new Document();  
  89.   
  90.         String category = file.getParent().substring(rootDir.length());  
  91.         category = category.replace(File.separatorChar, '/');  
  92.   
  93.         String isbn = props.getProperty("isbn");  
  94.         String title = props.getProperty("title");  
  95.         String author = props.getProperty("author");  
  96.         String url = props.getProperty("url");  
  97.         String subject = props.getProperty("subject");  
  98.   
  99.         String pubmonth = props.getProperty("pubmonth");  
  100.   
  101.         System.out.println("title:" + title + "\n" + "author:" + author + "\n" + "subject:" + subject + "\n"  
  102.                 + "pubmonth:" + pubmonth + "\n" + "category:" + category + "\n---------");  
  103.   
  104.         doc.add(new StringField("isbn", isbn, Field.Store.YES));  
  105.         doc.add(new StringField("category", category, Field.Store.YES));  
  106.         doc.add(new SortedDocValuesField("category"new BytesRef(category)));  
  107.         doc.add(new TextField("title", title, Field.Store.YES));  
  108.         doc.add(new Field("title2", title.toLowerCase(), Field.Store.YES,  
  109.                 Field.Index.NOT_ANALYZED_NO_NORMS,  
  110.                 Field.TermVector.WITH_POSITIONS_OFFSETS));  
  111.   
  112.         String[] authors = author.split(",");  
  113.         for (String a : authors) {  
  114.             doc.add(new Field("author", a, Field.Store.YES,  
  115.                     Field.Index.NOT_ANALYZED,  
  116.                     Field.TermVector.WITH_POSITIONS_OFFSETS));  
  117.         }  
  118.   
  119.         doc.add(new Field("url", url, Field.Store.YES,  
  120.                 Field.Index.NOT_ANALYZED_NO_NORMS));  
  121.         doc.add(new Field("subject", subject, Field.Store.YES,  
  122.                 Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));  
  123.   
  124.         doc.add(new IntField("pubmonth", Integer.parseInt(pubmonth),  
  125.                 Field.Store.YES));  
  126.         doc.add(new NumericDocValuesField("pubmonth", Integer.parseInt(pubmonth)));  
  127.         Date d = null;  
  128.         try {  
  129.             d = DateTools.stringToDate(pubmonth);  
  130.         } catch (ParseException pe) {  
  131.             throw new RuntimeException(pe);  
  132.         }  
  133.         doc.add(new IntField("pubmonthAsDay",  
  134.                 (int) (d.getTime() / (1000 * 3600 * 24)), Field.Store.YES));  
  135.           
  136.         for (String text : new String[] { title, subject, author, category }) {  
  137.             doc.add(new Field("contents", text, Field.Store.NO,  
  138.                     Field.Index.ANALYZED,  
  139.                     Field.TermVector.WITH_POSITIONS_OFFSETS));  
  140.         }  
  141.         return doc;  
  142.     }  
  143.   
  144. }  

 不要问我为什么上面创建索引还要用已经提示快要被废弃了的Field类呢,我会告诉你:我任性!!!不要在意那些细节,我只是想变着花样玩玩。其实就是读取data文件夹下的所有properties文件然后读取文件里的数据写入索引。我待会儿会在底下附件里上传测试用的properties数据文件。

然后就是编写测试类进行测试:

Java代码   收藏代码
  1. package com.yida.framework.lucene5.sort;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintStream;  
  5. import java.nio.file.Paths;  
  6. import java.text.DecimalFormat;  
  7.   
  8. import org.apache.commons.lang.StringUtils;  
  9. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  10. import org.apache.lucene.document.Document;  
  11. import org.apache.lucene.index.DirectoryReader;  
  12. import org.apache.lucene.index.IndexReader;  
  13. import org.apache.lucene.queryparser.classic.QueryParser;  
  14. import org.apache.lucene.search.BooleanClause;  
  15. import org.apache.lucene.search.BooleanQuery;  
  16. import org.apache.lucene.search.IndexSearcher;  
  17. import org.apache.lucene.search.MatchAllDocsQuery;  
  18. import org.apache.lucene.search.Query;  
  19. import org.apache.lucene.search.ScoreDoc;  
  20. import org.apache.lucene.search.Sort;  
  21. import org.apache.lucene.search.SortField;  
  22. import org.apache.lucene.search.SortField.Type;  
  23. import org.apache.lucene.search.TopDocs;  
  24. import org.apache.lucene.store.Directory;  
  25. import org.apache.lucene.store.FSDirectory;  
  26.   
  27. public class SortingExample {  
  28.     private Directory directory;  
  29.   
  30.     public SortingExample(Directory directory) {  
  31.         this.directory = directory;  
  32.     }  
  33.       
  34.     public void displayResults(Query query, Sort sort)  
  35.             throws IOException {  
  36.         IndexReader reader = DirectoryReader.open(directory);  
  37.         IndexSearcher searcher = new IndexSearcher(reader);  
  38.   
  39.         //searcher.setDefaultFieldSortScoring(true, false);  
  40.           
  41.         //Lucene5.x把是否评分的两个参数放到方法入参里来进行设置  
  42.         //searcher.search(query, filter, n, sort, doDocScores, doMaxScore);  
  43.         TopDocs results = searcher.search(query, null,   
  44.                 20, sort,true,false);   
  45.   
  46.         System.out.println("\nResults for: " +   
  47.                 query.toString() + " sorted by " + sort);  
  48.   
  49.         System.out  
  50.                 .println(StringUtils.rightPad("Title"30)  
  51.                         + StringUtils.rightPad("pubmonth"10)  
  52.                         + StringUtils.center("id"4)  
  53.                         + StringUtils.center("score"15));  
  54.         PrintStream out = new PrintStream(System.out, true"UTF-8");  
  55.   
  56.         DecimalFormat scoreFormatter = new DecimalFormat("0.######");  
  57.         for (ScoreDoc sd : results.scoreDocs) {  
  58.             int docID = sd.doc;  
  59.             float score = sd.score;  
  60.             Document doc = searcher.doc(docID);  
  61.             out.println(StringUtils.rightPad(   
  62.                     StringUtils.abbreviate(doc.get("title"), 29), 30) +   
  63.                     StringUtils.rightPad(doc.get("pubmonth"), 10) +   
  64.                     StringUtils.center("" + docID, 4) +   
  65.                     StringUtils.leftPad(   
  66.                             scoreFormatter.format(score), 12));   
  67.             out.println("   " + doc.get("category"));  
  68.             // out.println(searcher.explain(query, docID));   
  69.         }  
  70.         System.out.println("\n**************************************\n");  
  71.         reader.close();  
  72.     }  
  73.   
  74.     public static void main(String[] args) throws Exception {  
  75.         String indexdir = "C:/lucenedir";  
  76.         Query allBooks = new MatchAllDocsQuery();  
  77.   
  78.         QueryParser parser = new QueryParser("contents",new StandardAnalyzer());   
  79.         BooleanQuery query = new BooleanQuery();   
  80.         query.add(allBooks, BooleanClause.Occur.SHOULD);   
  81.         query.add(parser.parse("java OR action"), BooleanClause.Occur.SHOULD);   
  82.   
  83.         Directory directory = FSDirectory.open(Paths.get(indexdir));  
  84.         SortingExample example = new SortingExample(directory);   
  85.   
  86.         example.displayResults(query, Sort.RELEVANCE);  
  87.   
  88.         example.displayResults(query, Sort.INDEXORDER);  
  89.   
  90.         example.displayResults(query, new Sort(new SortField("category",  
  91.                 Type.STRING)));  
  92.   
  93.         example.displayResults(query, new Sort(new SortField("pubmonth",  
  94.                 Type.INT, true)));  
  95.   
  96.         example.displayResults(query, new Sort(new SortField("category",  
  97.                 Type.STRING), SortField.FIELD_SCORE, new SortField(  
  98.                 "pubmonth", Type.INT, true)));  
  99.   
  100.         example.displayResults(query, new Sort(new SortField[] {  
  101.                 SortField.FIELD_SCORE,  
  102.                 new SortField("category", Type.STRING) }));  
  103.         directory.close();  
  104.     }  
  105. }  

 理解清楚了我上面说的那些知识点,我想这些测试代码你们应该看得懂,不过我还是要提醒一点,在new Sort对象时,可以传入多个SortField来支持多域排序,比如:

    

Java代码   收藏代码
  1. new Sort(new SortField("category",  
  2.                 Type.STRING), SortField.FIELD_SCORE, new SortField(  
  3.                 "pubmonth", Type.INT, true))  

 表示先按category域按字符串升序排,再按评分降序排,接着按pubmonth域进行数字比较后降序排,一句话,域的排序顺序跟你StoreField定义的先后顺序保持一致。注意Sort的默认排序行为。

     下面是运行后的打印结果,你们请对照这打印结构和代码多理解酝酿下吧:

Java代码   收藏代码
  1. Results for: *:* (contents:java contents:action) sorted by <score>  
  2. Title                         pubmonth   id      score       
  3. Ant in Action                 200707     6      1.052735  
  4.    /technology/computers/programming  
  5. Lucene in Action, Second E... 201005     9      1.052735  
  6.    /technology/computers/programming  
  7. Tapestry in Action            200403     11     0.447534  
  8.    /technology/computers/programming  
  9. JUnit in Action, Second Ed... 201005     8      0.429442  
  10.    /technology/computers/programming  
  11. A Modern Art of Education     200403     0      0.151398  
  12.    /education/pedagogy  
  13. Imperial Secrets of Health... 199903     1      0.151398  
  14.    /health/alternative/chinese  
  15. Lipitor, Thief of Memory      200611     2      0.151398  
  16.    /health  
  17. Nudge: Improving Decisions... 200804     3      0.151398  
  18.    /health  
  19. Tao Te Ching 道德經              200609     4      0.151398  
  20.    /philosophy/eastern  
  21. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  22.    /technology/computers/ai  
  23. Mindstorms: Children, Comp... 199307     7      0.151398  
  24.    /technology/computers/programming/education  
  25. Extreme Programming Explained 200411     10     0.151398  
  26.    /technology/computers/programming/methodology  
  27. The Pragmatic Programmer      199910     12     0.151398  
  28.    /technology/computers/programming  
  29.   
  30. **************************************  
  31.   
  32.   
  33. Results for: *:* (contents:java contents:action) sorted by <doc>  
  34. Title                         pubmonth   id      score       
  35. A Modern Art of Education     200403     0      0.151398  
  36.    /education/pedagogy  
  37. Imperial Secrets of Health... 199903     1      0.151398  
  38.    /health/alternative/chinese  
  39. Lipitor, Thief of Memory      200611     2      0.151398  
  40.    /health  
  41. Nudge: Improving Decisions... 200804     3      0.151398  
  42.    /health  
  43. Tao Te Ching 道德經              200609     4      0.151398  
  44.    /philosophy/eastern  
  45. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  46.    /technology/computers/ai  
  47. Ant in Action                 200707     6      1.052735  
  48.    /technology/computers/programming  
  49. Mindstorms: Children, Comp... 199307     7      0.151398  
  50.    /technology/computers/programming/education  
  51. JUnit in Action, Second Ed... 201005     8      0.429442  
  52.    /technology/computers/programming  
  53. Lucene in Action, Second E... 201005     9      1.052735  
  54.    /technology/computers/programming  
  55. Extreme Programming Explained 200411     10     0.151398  
  56.    /technology/computers/programming/methodology  
  57. Tapestry in Action            200403     11     0.447534  
  58.    /technology/computers/programming  
  59. The Pragmatic Programmer      199910     12     0.151398  
  60.    /technology/computers/programming  
  61.   
  62. **************************************  
  63.   
  64.   
  65. Results for: *:* (contents:java contents:action) sorted by <string: "category">  
  66. Title                         pubmonth   id      score       
  67. A Modern Art of Education     200403     0      0.151398  
  68.    /education/pedagogy  
  69. Lipitor, Thief of Memory      200611     2      0.151398  
  70.    /health  
  71. Nudge: Improving Decisions... 200804     3      0.151398  
  72.    /health  
  73. Imperial Secrets of Health... 199903     1      0.151398  
  74.    /health/alternative/chinese  
  75. Tao Te Ching 道德經              200609     4      0.151398  
  76.    /philosophy/eastern  
  77. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  78.    /technology/computers/ai  
  79. Ant in Action                 200707     6      1.052735  
  80.    /technology/computers/programming  
  81. JUnit in Action, Second Ed... 201005     8      0.429442  
  82.    /technology/computers/programming  
  83. Lucene in Action, Second E... 201005     9      1.052735  
  84.    /technology/computers/programming  
  85. Tapestry in Action            200403     11     0.447534  
  86.    /technology/computers/programming  
  87. The Pragmatic Programmer      199910     12     0.151398  
  88.    /technology/computers/programming  
  89. Mindstorms: Children, Comp... 199307     7      0.151398  
  90.    /technology/computers/programming/education  
  91. Extreme Programming Explained 200411     10     0.151398  
  92.    /technology/computers/programming/methodology  
  93.   
  94. **************************************  
  95.   
  96.   
  97. Results for: *:* (contents:java contents:action) sorted by <int"pubmonth">!  
  98. Title                         pubmonth   id      score       
  99. JUnit in Action, Second Ed... 201005     8      0.429442  
  100.    /technology/computers/programming  
  101. Lucene in Action, Second E... 201005     9      1.052735  
  102.    /technology/computers/programming  
  103. Nudge: Improving Decisions... 200804     3      0.151398  
  104.    /health  
  105. Ant in Action                 200707     6      1.052735  
  106.    /technology/computers/programming  
  107. Lipitor, Thief of Memory      200611     2      0.151398  
  108.    /health  
  109. Tao Te Ching 道德經              200609     4      0.151398  
  110.    /philosophy/eastern  
  111. Extreme Programming Explained 200411     10     0.151398  
  112.    /technology/computers/programming/methodology  
  113. A Modern Art of Education     200403     0      0.151398  
  114.    /education/pedagogy  
  115. Tapestry in Action            200403     11     0.447534  
  116.    /technology/computers/programming  
  117. The Pragmatic Programmer      199910     12     0.151398  
  118.    /technology/computers/programming  
  119. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  120.    /technology/computers/ai  
  121. Imperial Secrets of Health... 199903     1      0.151398  
  122.    /health/alternative/chinese  
  123. Mindstorms: Children, Comp... 199307     7      0.151398  
  124.    /technology/computers/programming/education  
  125.   
  126. **************************************  
  127.   
  128.   
  129. Results for: *:* (contents:java contents:action) sorted by <string: "category">,<score>,<int"pubmonth">!  
  130. Title                         pubmonth   id      score       
  131. A Modern Art of Education     200403     0      0.151398  
  132.    /education/pedagogy  
  133. Nudge: Improving Decisions... 200804     3      0.151398  
  134.    /health  
  135. Lipitor, Thief of Memory      200611     2      0.151398  
  136.    /health  
  137. Imperial Secrets of Health... 199903     1      0.151398  
  138.    /health/alternative/chinese  
  139. Tao Te Ching 道德經              200609     4      0.151398  
  140.    /philosophy/eastern  
  141. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  142.    /technology/computers/ai  
  143. Lucene in Action, Second E... 201005     9      1.052735  
  144.    /technology/computers/programming  
  145. Ant in Action                 200707     6      1.052735  
  146.    /technology/computers/programming  
  147. Tapestry in Action            200403     11     0.447534  
  148.    /technology/computers/programming  
  149. JUnit in Action, Second Ed... 201005     8      0.429442  
  150.    /technology/computers/programming  
  151. The Pragmatic Programmer      199910     12     0.151398  
  152.    /technology/computers/programming  
  153. Mindstorms: Children, Comp... 199307     7      0.151398  
  154.    /technology/computers/programming/education  
  155. Extreme Programming Explained 200411     10     0.151398  
  156.    /technology/computers/programming/methodology  
  157.   
  158. **************************************  
  159.   
  160.   
  161. Results for: *:* (contents:java contents:action) sorted by <score>,<string: "category">  
  162. Title                         pubmonth   id      score       
  163. Ant in Action                 200707     6      1.052735  
  164.    /technology/computers/programming  
  165. Lucene in Action, Second E... 201005     9      1.052735  
  166.    /technology/computers/programming  
  167. Tapestry in Action            200403     11     0.447534  
  168.    /technology/computers/programming  
  169. JUnit in Action, Second Ed... 201005     8      0.429442  
  170.    /technology/computers/programming  
  171. A Modern Art of Education     200403     0      0.151398  
  172.    /education/pedagogy  
  173. Lipitor, Thief of Memory      200611     2      0.151398  
  174.    /health  
  175. Nudge: Improving Decisions... 200804     3      0.151398  
  176.    /health  
  177. Imperial Secrets of Health... 199903     1      0.151398  
  178.    /health/alternative/chinese  
  179. Tao Te Ching 道德經              200609     4      0.151398  
  180.    /philosophy/eastern  
  181. Gödel, Escher, Bach: an Et... 199905     5      0.151398  
  182.    /technology/computers/ai  
  183. The Pragmatic Programmer      199910     12     0.151398  
  184.    /technology/computers/programming  
  185. Mindstorms: Children, Comp... 199307     7      0.151398  
  186.    /technology/computers/programming/education  
  187. Extreme Programming Explained 200411     10     0.151398  
  188.    /technology/computers/programming/methodology  
  189.   
  190. **************************************  

    写的比较匆忙,如果有哪里没有说清楚或说的不对的,请尽情的喷我,谢谢!

    demo源码我也会上传到底下的附件里,你们运行测试类的时候,记得把测试用的数据文件copy到C盘下,如图:


 

    OK,打完收工!

   

      如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,

或者加裙
一起交流学习!

转载:http://iamyida.iteye.com/blog/2197839

目录
相关文章
|
7月前
排序——sort的用法
排序——sort的用法
57 0
|
搜索推荐 C++
C++利用sort进行排序
C++利用sort进行排序
|
7月前
|
搜索推荐 数据库 C++
带用排序等法sort讲解
带用排序等法sort讲解
44 0
|
7月前
|
C++
C++如何进行sort的使用——C++如何进行排序
C++如何进行sort的使用——C++如何进行排序
125 0
|
7月前
|
小程序
排序sort()排序用法
排序sort()排序用法
排序(Sort)(一)
排序(Sort)(一)
87 0
排序(Sort)(二)
排序(Sort)(二)
67 0
|
自然语言处理 算法 Java
11Lucene相关度排序
11Lucene相关度排序
63 0
|
算法 搜索推荐
排序篇(六)----排序小结
排序篇(六)----排序小结
47 0
|
存储 搜索推荐
十大排序之Merge Sort 归并排序
十大排序之Merge Sort 归并排序