bontade
bontade

Reputation: 3224

Hibernate + Lucene - wildard search returning empty result

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

Answers (3)

bontade
bontade

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

Mincong Huang
Mincong Huang

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

Guillaume Smet
Guillaume Smet

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

Related Questions