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