Reputation: 3224
I have written article about nice Hibernate search to search database tables by wildcards.
So I have added it to my pom.xml:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.5.4.Final</version>
</dependency>
set directory provider:
properties.put("hibernate.search.default.directory_provider", "ram");
and defined indexes on my entity to be visible for search mechanism:
@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;
// ...
}
Then I loaded manually from SQL script database table - CUSTOM_ENTITY:
ID |NAME1 |NAME2 |NAME3 |
-------------------------
1 |Test1 |Test1 |Test1 |
2 |Test2 |Test2 |Test2 |
3 |Test3 |Test2 |Test2 |
and run code in my repository:
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();
However each time result collection is empty. Do you know if I missed any step? Should I load data with Hibernate API instead of SQL scripts?
EDIT
Befor running query I am indexing data manually:
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();
Result is still the same.
Thank you for help.
Upvotes: 1
Views: 788
Reputation: 3224
Issue is solved. Issue was related to the camel case "search string".
I noticed that even if I have values stored in database like:
ID |NAME1 |NAME2 |NAME3 |
-------------------------
1 |Test1 |Test1 |Test1 |
2 |Test2 |Test2 |Test2 |
3 |Test3 |Test2 |Test2 |
Lucene is not able to search by string Test*:
Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("Test*").createQuery();
When I changed my query to this:
Query luceneQuery = qBuilder.keyword().wildcard().onFields("name1", "name2", "name3").matching("test*").createQuery();
Everything is working fine. I do not know yet why, but it fixed the issue.
Thank you for your time and help.
Upvotes: 1
Reputation: 5552
After having indexed all the entities before searching, you need a correct wildcard query with ?
or *
. The character ?
represents a single character and *
represents any character sequence:
Assume that you've the below table :
ID | NAME1 | NAME2 | NAME3 |
-------------------------------
1 | test1 | test1 | test1 |
2 | test2 | test2 | test2 |
3 | test3 | test3 | test3 |
4 | test4A | test4B | test4C |
Then with ?
you'll obtain 3 results and with *
you'll obtain 4 results.
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();
Upvotes: 0
Reputation: 10539
If you load your data using SQL, you need to index the data manually using the Mass indexer. See https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-batchindex-massindexer .
If you're using the Hibernate API, they will be indexed automatically.
Upvotes: 1