Hibernate + Lucene - wildard搜索返回空结果

时间:2016-08-09 12:53:24

标签: java hibernate lucene hibernate-search

我写过关于通过通配符搜索数据库表的好Hibernate搜索的文章。

所以我把它添加到我的pom.xml:

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-search-orm</artifactId>
        <version>5.5.4.Final</version>
    </dependency>

设置目录提供程序:

properties.put("hibernate.search.default.directory_provider", "ram");

并且我的实体上定义的索引对于搜索机制是可见的:

@Entity
@Table(name = "CUSTOM_ENTITY")
@Audited
@Indexed
public class CustomEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    @DocumentId
    private Long id;

    @Column(name = "NAME1", nullable = false)
    @NotEmpty
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    private String name1;

    @Column(name = "NAME2", nullable = false)
    @NotEmpty
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    private String name2;

    @Column(name = "NAME3", nullable = false)
    @NotEmpty
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    private String name3;

    // ...
}

然后我从SQL脚本数据库表 - CUSTOM_ENTITY:

手动加载
ID |NAME1 |NAME2 |NAME3 |
-------------------------
1  |Test1 |Test1 |Test1 |
2  |Test2 |Test2 |Test2 |
3  |Test3 |Test2 |Test2 |

并在我的存储库中运行代码:

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);

QueryBuilder qBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(CustomEntity.class).get();

Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test").createQuery();
// Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test*").createQuery();
// Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test%").createQuery();

List test = fullTextEntityManager.createFullTextQuery(luceneQuery, CustomEntity.class).getResultList();

但每次结果收集都是空的。你知道我错过了什么步骤吗?我应该使用Hibernate API而不是SQL脚本加载数据吗?

修改

Befor运行查询我手动索引数据:

FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
try {
    fullTextEntityManager.createIndexer().startAndWait();
} catch (InterruptedException e) {
    e.printStackTrace();
}
QueryBuilder qBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(CustomEntity.class).get();

Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test").createQuery();
// Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test*").createQuery();
// Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test%").createQuery();

List test = fullTextEntityManager.createFullTextQuery(luceneQuery, CustomEntity.class).getResultList();

结果仍然相同。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

如果使用SQL加载数据,则需要使用Mass索引器手动索引数据。请参阅https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-batchindex-massindexer

如果您正在使用Hibernate API,它们将被自动编入索引。

答案 1 :(得分:0)

在搜索之前having indexed所有实体之后,您需要使用?*进行正确的通配符查询。字符?表示单个字符,*表示任何字符序列:

假设你有以下表格:

ID | NAME1  | NAME2  | NAME3  |
-------------------------------
1  | test1  | test1  | test1  |
2  | test2  | test2  | test2  |
3  | test3  | test3  | test3  |
4  | test4A | test4B | test4C |

然后使用?,您将获得3个结果,使用*,您将获得4个结果。

Query luceneQuery = qBuilder.keyword()
    .wildcard()
    .onFields("name1", "name2", "name3")
    .matching("test?")  // return {1, 2, 3}
//  .matching("test*")  // return {1, 2, 3, 4}
//  .matching("test")   // return {}
    .createQuery();

答案 2 :(得分:0)

问题解决了。问题与驼峰案例“搜索字符串”有关。

我注意到即使我将值存储在数据库中,例如:

ID |NAME1 |NAME2 |NAME3 |
-------------------------
1  |Test1 |Test1 |Test1 |
2  |Test2 |Test2 |Test2 |
3  |Test3 |Test2 |Test2 |

Lucene无法通过字符串Test *搜索:

Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test*").createQuery();

当我将查询更改为:

Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("test*").createQuery();

一切都很好。我不知道为什么,但它解决了这个问题。

感谢您的时间和帮助。