代码之家  ›  专栏  ›  技术社区  ›  Mauricio Ubilla Carvajal

Hibernate搜索:如何在单独的列上搜索全名

  •  1
  • Mauricio Ubilla Carvajal  · 技术社区  · 7 年前

    我有一个名为“Patient”的实体,带有名为“firstName”、“lastName”和“secondLastName”的字符串字段(在西班牙语中,我们同时使用父亲和母亲的姓氏)

    我有一个按姓名搜索患者的文本框,用户可以在其中键入任何内容:firstName、lastName、secondLastName,或它们的组合,按任何给定的顺序。 例如,用我的名字:

    名字:毛里西奥, 第二姓氏:Carvajal,

    如果我搜索“Mauricio Ubilla Carvajal”甚至“Mauricio Ubilla”,我希望在结果列表中排名第一。 问题是:

    @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();
    

    然而,这对我不起作用。它没有抛出任何异常,只是没有返回任何内容。

    但是,如果我只更改查询以匹配我的名字:

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

    请帮帮我:( 顺便说一句,我使用的是Hibernate Search 4.5.1,而不是Hibernate 4.3和Java 1.7

    2 回复  |  直到 7 年前
        1
  •  2
  •   yrodiere    7 年前

    您使用的是一个非常旧的Hibernate搜索版本,因此很可能您遇到了一个已在较新版本中解决的错误。您真的应该考虑升级到Hibernate Search 5.6/Hibernate ORM 5.1,或者更好地升级到Search 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 字段禁用某些优化。但至少它应该起作用。

        2
  •  0
  •   geobudex    6 年前

    回答你的第二个问题。您可以使用短语作为句子而不是关键字进行搜索。

    Hibernate Search还支持使用各种策略组合查询:

    -应:查询应包含子查询的匹配元素

    -必须:查询必须包含子查询的匹配元素

    -不得:查询不得包含子查询的匹配元素

        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