2017-10-18 170 views
0

我有一個名爲'Patient'的字符串字段名爲'firstName','lastName'和'secondLastName'的實體(在西班牙語中,我們同時使用父親和母親姓氏)Hibernate搜索:如何通過單獨的列搜索全名

我有一個文本框按照名稱搜索患者的視圖,其中用戶可以按任何給定順序鍵入任何內容:firstName,lastName,secondLastName或這些的組合。 例如,我的名字:

姓:毛, 名字:Ubilla, secondLastName:卡瓦哈爾,

如果我搜索「毛Ubilla卡瓦哈爾」,甚至「毛Ubilla」我希望能出現頂部結果列表。 問題是:

1-我應該如何定義這3個字段的索引?我做了以下幾點:

@Indexed 
class Patient { 
    ... 
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO) 
    protected String firstName = new String(); 
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO) 
    protected String lastName = new String(); 
    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO) 
    protected String secondLastName = new String(); 
    ... 
} 

2-我該如何構建查詢?我這樣做:

QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();   
Query luceneQuery = qb.keyword().onFields("firstName", "lastName", "secondLastName").matching(name).createQuery(); 

但是,這不適合我。它沒有拋出任何異常,只是它沒有返回任何東西。 即使我只搜索「Mauricio」,它也不會返回任何內容。

但是,如果我更改查詢只符合我的姓:如果我搜索

QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();   
Query luceneQuery = qb.keyword().onFields("firstName").matching(name).createQuery(); 

「毛」它的工作原理。

我在做什麼錯?有什麼辦法可以爲3列定義組合索引嗎?我應該以不同的方式構建我的查詢嗎? 請幫助我順便說一句:( ,我使用Hibernate Search的4.5.1在休眠4.3和Java 1.7

回答

2

您使用的是很舊版本的Hibernate搜索的,所以這是非常可能的,你正在運行到一個錯誤你應該考慮升級到至少Hibernate Search 5.6/Hibernate ORM 5.1,或者甚至更好的搜索5.8/ORM 5.2(需要Java 8)

如果你不能。另一個常見的解決方案是索引一個瞬變屬性,其內容是連接名稱:

@Indexed 
class Patient { 
    ... 
    @Field 
    protected String firstName = ""; 
    @Field 
    protected String lastName = ""; 
    @Field 
    protected String secondLastName = ""; 
    ... 
    @javax.persistence.Transient 
    @Field 
    public String getFullName() { 
     // TODO null safety 
     return firstName + " " + lastName + " " + secondLastName; 
    } 
    ... 
} 

這個fullName然後查詢:

QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();   
Query luceneQuery = qb.keyword().onFields("fullName").matching(name).createQuery(); 

需要注意的是,就違背了你最初的解決方案,這會對性能產生負面影響,因爲索引一個@Transient場禁用一些優化。但至少它應該工作。

+0

謝謝獲得!這就是我所做的,它工作正常。同時感謝您對升級到更新版本hibernate的建議。好像我很快就要做。 –

0

回答你的第二個問題。您可以使用短語作爲句子而不是關鍵字。

Hibernate Search的使用也不同戰略支持相結合的查詢:

-SHOULD:查詢應包含的子查詢匹配元素

- 必須:查詢必須包含子查詢的匹配元素

- 必須:查詢不得包含子查詢的匹配元素

聚合類似於布爾邏輯的AND,OR和NOT。

Query combinedQuery = queryBuilder 
    .bool() 

    .must(queryBuilder.phrase() 
    .onField("productName).sentence("samsung galaxy s8") 
    .createQuery()) 

    .must(queryBuilder.keyword() 
    .onField("productCategory").matching("smartphone") 
    .createQuery()) 

    .createQuery(); 


    // wrap Lucene query in an Hibernate Query object 
    org.hibernate.search.jpa.FullTextQuery jpaQuery = 
    fullTextEntityManager.createFullTextQuery(combinedQuery, Product.class); 

    // execute search and return results (sorted by relevance as default) 
    @SuppressWarnings("unchecked") 
    List<Product> results = jpaQuery.getResultList(); 

此引用從鏈接http://www.baeldung.com/hibernate-search