2017-10-18 3 views
0

'firstName', 'lastName'및 'secondLastName'이라는 문자열 필드가있는 'Patient'라는 엔티티가 있습니다 (스페인어로는 아버지와 어머니의 가족 이름)Hibernate Search : 별도의 열을 통해 전체 이름을 검색하는 방법

환자 이름을 입력하여 환자를 검색 할 수있는 텍스트 상자가 있습니다. 사용자는 firstName, lastName, secondLastName 또는 이들의 조합을 임의의 순서로 입력 할 수 있습니다. 예를 들어, 내 이름 :

인 firstName : 마우, 이 lastName : 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"만 검색하더라도 아무 것도 반환하지 않습니다. 내가 쿼리를 변경하는 경우 단지 내 firstName을 일치

그러나 : 나는 검색하면

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

은 "마우는"그것은 작동합니다.

내가 뭘 잘못하고 있니? 3 열의 복합 인덱스를 정의하는 방법이 있습니까? 다른 방법으로 쿼리를 작성해야합니까? 이 버그로 실행하는 것이 매우 가능성이 있으므로 , 나는 하이버 네이트 검색 4.5.1 이상 최대 절전 모드 4.3과 자바 1.7

답변

2

당신은 최대 절전 모드 검색의 아주 오래된 버전을 사용을 사용하고, 내가 Btw는 을 :(제발 도와주세요 보다 최신 버전에서 해결되었으므로 적어도 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이에 쿼리하십시오 @Transient 필드를 색인하는 몇 가지 최적화를 비활성화 이후 최초의 솔루션에 반대로,이 성능에 부정적인 영향을 미칠 것이다,

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

참고. 하지만 적어도 작동해야합니다.

+0

감사합니다 링크에서 얻을 수있다! 그게 내가 끝난거야 그리고 잘 작동합니다. 또한 최신 버전의 최대 절전 모드로 업그레이드하는 것에 대해 조언 해 주셔서 감사합니다. 곧해야 할 것 같은데. –

0

두 번째 질문에 답변하십시오. 키워드가 아닌 문장으로 구문을 사용하여 검색 할 수 있습니다.

최대 절전 모드 검색은 다양한 전략을 사용하여 결합 쿼리를 지원합니다

될까요, 아빠 : 서브 쿼리의 일치하는 요소를 포함해야 쿼리

-MUST : 쿼리는 서브 쿼리의 일치하는 요소를 포함해야한다

-MUST NOT : 쿼리에 하위 쿼리와 일치하는 요소가 없어야합니다.

집계는 부울 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

관련 문제