365
汽车大全
5. Querying
Chapter 5. Querying
-
创建
FullTextSession
-
创建Lucene query,通过Hibernate Search query DSL (recommended)或者使用Lucene query API
-
Wrapping the Lucene query using an
org.hibernate.Query
-
执行查询-->
list()
orscroll()
Example 5.1. Creating a FullTextSession
Session session = sessionFactory.openSession();
...
FullTextSession fullTextSession =Search.getFullTextSession(session);
final QueryBuilder b = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity( Myth.class ).get(); org.apache.lucene.search.Query luceneQuery = b.keyword() .onField("history").boostedTo(3) .matching("storm") .createQuery(); org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );List result = fullTextQuery.list();//return a list of managed objects
Example 5.2. Creating a Lucene query via the QueryParser
SearchFactory searchFactory = fullTextSession.getSearchFactory(); org.apache.lucene.queryParser.QueryParser parser = new QueryParser("title", searchFactory.getAnalyzer(Myth.class) ); try { org.apache.lucene.search.Query luceneQuery = parser.parse( "history:storm^3" ); } catch (ParseException e) { //handle parsing failure } org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery);List result = fullTextQuery.list();//return a list of managed objects
Note
Hibernate query方法是基于lucene query的:org.hibernate.Query
, 这意味着Hibernate query也支持HQL, Native or Criteria). The regular list()
, uniqueResult()
, iterate()
and scroll()等平常我们使用的方法
Example 5.3. Creating a Search query using the JPA API
EntityManager em = entityManagerFactory.createEntityManager(); FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(em); ...finalQueryBuilder b = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Myth.class).get(); org.apache.lucene.search.Query luceneQuery = b.keyword().onField("history").boostedTo(3).matching("storm").createQuery(); javax.persistence.Query fullTextQuery = fullTextEntityManager.createFullTextQuery( luceneQuery ); List result = fullTextQuery.getResultList();//return a list of managed objects
Note
接下来的例子都是介绍hibernate apis,但是可以很方便的转换到jpa方式、
-
方法名言简意赅
-
方便使用和阅读
-
storm这个值通过history桥
-
桥的值之后会传递给分析器,分析器对索引进行匹配。
@Entity@IndexedpublicclassMyth{ @Field(analyze =Analyze.NO) @DateBridge(resolution =Resolution.YEAR)publicDate getCreationDate(){return creationDate;}publicDate setCreationDate(Date creationDate){this.creationDate = creationDate;}privateDate creationDate;...} Date birthdate =...;Query luceneQuery = mythQb.keyword().onField("creationDate").matching(birthdate).createQuery();
Note
使用lucene必须将日期转化为String类型。而hibernate search不用
Note
如果不想使用桥(field bridge)或者分析器,可以使用ignoreAnalyzer()和ignoreFieldBridge()
threshold(
临界值)规定了两个terms被认为相同(匹配)的上限,是0~1之间的数,默认是0.5。prefixLength(前缀长度)说明了模糊性(被忽略的前缀长度):如果被设置为0,则任意一个非零的值被推荐(估计是匹配所有)
//look for popular modern myths that are not urban
DatetwentiethCentury =...;
Query luceneQuery = mythQB.bool().must( mythQB.keyword().onField("description").matching("urban").createQuery()).not().must( mythQB.range().onField("starred").above(4).createQuery()).must( mythQB.range().onField("creationDate").above(twentiethCentury).createQuery()).createQuery();
//look for popular myths that are preferably urban
Query luceneQuery = mythQB.bool().should( mythQB.keyword().onField("description").matching("urban").createQuery()).must( mythQB.range().onField("starred").above(4).createQuery() ).createQuery();
//look for all myths except religious ones
Query luceneQuery = mythQB.all().except( monthQb.keyword().onField("description_stem").matching("religion").createQuery()).createQuery();
5.1.2.7. Query options
?
boostedTo:可以用在查询实体或字段中,使用给定的因子提升整个查询或特定字段。
?
withConstantScore
(on query):和boost(作用)一样,所有匹配的查询结果有一个常量分数。
?
filteredBy
(on query):使用过滤器过滤查询结果。
? ignoreAnalyzer
(on field):处理字段时忽略analyzer。
? ignoreFieldBridge
(on field):处理字段时忽略field
bridge。
.bool()
.should( mythQB.keyword().onField("description").matching("urban").createQuery() )
.should( mythQB
.keyword()
.onField("name")
.boostedTo(3)
.ignoreAnalyzer()
.matching("urban").createQuery() )
.must( mythQB
.range()
.boostedTo(5).withConstantScore()
.onField("starred").above(4).createQuery() )
.createQuery();
一旦Lucene Query被创建,他需要被包装成一个Hibernate查询。如果没有特殊说明,它将会对所有的索引实体进行查询,可能返回所有的索引类的类型。
Example 5.5. Filtering the search result by entity type
fullTextQuery = fullTextSession .createFullTextQuery( luceneQuery, Customer.class ); // or fullTextQuery = fullTextSession .createFullTextQuery( luceneQuery, Item.class, Actor.class );
Example 5.6. Defining pagination for a search query
org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery, Customer.class );
fullTextQuery.setFirstResult(15); //start from the 15th
elementfullTextQuery.setMaxResults(10); //return 10 elements
Example 5.7. Specifying a Lucene Sort
in order to sort the results
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( query, Book.class );
org.apache.lucene.search.Sort sort = new Sort(new SortField("title", SortField.STRING)); query.setSort(sort); List results = query.list();
Example 5.8. Specifying FetchMode
on a query
Criteria criteria = s.createCriteria( Book.class ).setFetchMode( "authors", FetchMode.JOIN );
s.createFullTextQuery( luceneQuery ).setCriteriaQuery( criteria );
Example 5.9. Using projection instead of returning the full domain object
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( "id", "summary", "body", "mainAuthor.name" );
List results = query.list();
Object[] firstResult = (Object[]) results.get(0);
Integer id = firstResult[0];
String summary = firstResult[1];
String body = firstResult[2];
String authorName = firstResult[3];
Example 5.11. Check the second-level cache before using a query
FullTextQuery query = session.createFullTextQuery(luceneQuery, User.class);query.initializeObjectWith( ObjectLookupMethod.SECOND_LEVEL_CACHE, DatabaseRetrievalMethod.QUERY);
-
ObjectLookupMethod.PERSISTENCE_CONTEXT
: useful if most of the matching entities are already in the persistence context (ie loaded in theSession
orEntityManager
) -
ObjectLookupMethod.SECOND_LEVEL_CACHE
: check first the persistence context and then the second-level cache.
使用Hibernate Search进行全文检索时,你可以使用下面两种方式限制每次查询的时间:
? 当限定时间到时抛出异常
? 当限定时间到时限制查询结果的个数。(EXPERIMENTAL)
两种方式不兼容。
list()
, uniqueResult()
, iterate()
, scroll()
list()
or uniqueResult()。
list()
, uniqueResult()
and iterate()时,
注意hibernate
search会处理所有Lucene匹配的索引(包括分页)
Important
分页比用scrolling好
Example 5.16. Determining the result size of a query
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
//return the number of matching books without loading a single one
assert 3245 == query.getResultSize(); org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setMaxResult(10);List results = query.list();
//return the total number of matching books regardless of pagination
assert 3245 == query.getResultSize();
Example 5.17. Using ResultTransformer in conjunction with projections
org.hibernate.search.FullTextQuery query = s.createFullTextQuery( luceneQuery, Book.class );
query.setProjection( "title", "mainAuthor.name" ); query.setResultTransformer( new StaticAliasToBeanResultTransformer( BookView.class, "title", "author" ) ); List<BookView> results = (List<BookView>) query.list();
for(BookView view : results) {
log.info( "Book: " + view.getTitle() + ", " + view.getAuthor() );
}
Warning
Document ID 和 实体类的ID不是同一个东西
Example 5.18. Retrieving the Lucene Explanation object using projection
FullTextQuery ftQuery = s.createFullTextQuery( luceneQuery, Dvd.class )
.setProjection(
FullTextQuery.DOCUMENT_ID,
FullTextQuery.EXPLANATION,
FullTextQuery.THIS );
@SuppressWarnings("unchecked") List<Object[]> results = ftQuery.list();
for (Object[] result : results) {
Explanation e = (Explanation) result[1];
display( e.toString() );
}
Example 5.19. Enabling fulltext filters for a given query
fullTextQuery = s.createFullTextQuery( query, Driver.class );
fullTextQuery.enableFullTextFilter("bestDriver");
fullTextQuery.enableFullTextFilter("security").setParameter( "login", "andre" );
fullTextQuery.list(); //returns only best drivers where andre has credentials
Example 5.20. Defining and implementing a Filter
@Entity @Indexed @FullTextFilterDefs( { @FullTextFilterDef(name = "bestDriver", impl = BestDriversFilter.class), @FullTextFilterDef(name = "security", impl = SecurityFilterFactory.class) }) public class Driver { ... }
public class BestDriversFilter extends org.apache.lucene.search.Filter { public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
OpenBitSet bitSet = new OpenBitSet( reader.maxDoc() );
TermDocs termDocs = reader.termDocs( new Term( "score", "5" ) );
while ( termDocs.next() ) {
bitSet.set( termDocs.doc() ); } return bitSet; }}
最后更新:2017-04-03 18:52:02