“秩序,秩序”- 有时不仅仅下议院尊敬的议员需要被喊着让排序,而且在特殊情况下 Hibernate 的查询结果也需要排序。
就像这样,仅仅通过一个 Sort 对象在全文本查询执行之前,对特殊的属性进行排序。
FullTextSession session = ...; QueryParser queryParser = ...; FullTextQuery query = session.createFullTextQuery( queryParser.parse( "summary:lucene" ), Book.class ); Sort sort = new Sort( new SortField( "title", SortField.Type.STRING, false ) ); query.setSort( sort ); List<Book> result = query.list();
就像 Lucene 5 (基于 Hibernate Search 5.5)那样, 如果事先就知道排序属性,就能很好的提高性能 。在这个例子中,这些可以被排序属性称之为“文本值属性”,这些文本值属性比传统的未转化的索引的方法有快速和低内存消耗的优点。
为了达到那样的目的。Hibernate Search 提供新的注解 @SortableField (它的多值组合是, @SortableFields )可以标记那些可以被排序的属性。接下来的例子展示了它是怎么样做的:
@Entity @Indexed(index = "Book") public class Book { @Id private Integer id; @Field @SortableField @DateBridge(resolution = Resolution.DAY) private Date publicationDate; @Fields({ @Field, @Field(name = "sortTitle", analyze = Analyze.NO, store = Store.NO, index = Index.NO) }) @SortableField(forField = "sortTitle") private String title; @Field private String summary; // constructor, getters, setters ... }
用过了@SortableField ,接下来了解一下 @Field 注解。在这个例子中单独存在的字段对应一个属性(例如 publicationDate)仅仅使用一个特殊的 @SortableField 注解就足够让这个字段成为可排序字段。如果有多个存在的字段(如 title 属性),通过 @SortableField#forField() 可实现特殊的字段名。
注意, 排序字段一定不能被分析的 。在例子中为了搜索,你想给一个指定的分析属性建索引,只要为排序加上另一个未分析的字段作为 title 属性的显示。如果字段仅仅需要排序而不做其他事,你需要将它配置成非索引和非排序的,因此可避免不必要的索引被生成。
在不改变查询的情况下,对排序字段的配置。仅对需要的字段设定 Sort 就可以了:
FullTextQuery query = ...; Sort sort = new Sort( new SortField( "publicationDate", SortField.Type.LONG, false ), new SortField( "sortTitle", SortField.Type.STRING, false ) ); query.setSort( sort );
现在如果你对一个你还没有明确声明排序的字段排序,会怎么样?例如迁移一个已完成的应用到Hibernate Search 5.5?好消息是排序将会默认使用基本功能设定排序。 Hibernate Search 检测到未设置排序字段, 自然就回退到非倒排索引 。
但是你要知道这样做的话性能会差很多(同样也是 作为 非反转 内存操作 的 内存密集型 ),也许这个功能将要从 Lucene 的未来版本中完全的去除掉。因此注意在你的日志文件里的消息,像下面的这样。 听从 建议去 声明未声明的排序字段。
WARN ManagedMultiReader:142 - HSEARCH000289: Requested sort field(s) summary_forSort are not configured for entity / type org.hibernate.search.test.query.Book mapped to index Book, thus an uninverting reader must be created. You / should declare the missing sort fields using @SortField.
当迁移一个存在的项目,一定要 重建有效的索引, 这在 相关指导 里有详细描述。随着所有的需要排序字段被配置,你的查询结果会被排序,就像是 会议主持喊着让 英国的议会会员排队那样。