Question

I am trying to create a queries using wildcards and projections with hibernate search, but I'm failing. The users can use or not wildcard on queries. For example, I want to search all terms starting with "book", I use "book*" to search.

The method I've implemented, is below.

public List<Employee> filtrar(String term) throws DAOException {
    try {
        FullTextEntityManager fullTextEm = Search.getFullTextEntityManager(this.entityManager);

        Query query = new WildcardQuery(new Term("*", term));           

        FullTextQuery fullTextQuery = fullTextEm.createFullTextQuery(query, Employee.class);
        fullTextQuery.setProjection("id", "name", "phone", "email");
        Sort sortField = new Sort(new SortField("name_order", SortField.STRING));
        fullTextQuery.setSort(sortField);
        return fullTextQuery.getResultList();
    }
    catch (Exception e) {
        logger.error("Error: " + term, e);
        throw new DAOException(e);
    }
}

The String term passed, as parameter to method, is used to search on all fields(id, name, phone and email). Nothing is returned. What's wrong in that method?

EDIT: My entity

@Entity
@Indexed
@Table(name = "vw_employee")
public class Employee implements Serializable {

    private static final long serialVersionUID = 244555315052436669L;

    @Id
    @Column(name = "id", insertable = false, updatable = false)
    @Field(store = Store.YES, index = Index.YES, analyze = Analyze.NO)
    private Long id;

    @Fields({
        @Field(name = "name_order", store = Store.YES, index = Index.YES, analyze = Analyze.NO),
        @Field(name = "name", store = Store.YES, index = Index.YES, analyze = Analyze.YES)
    })
    @Column(name = "name", insertable = false, updatable = false)
    private String name;

    @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES)
    @Column(name = "phone", insertable = false, updatable = false)
    private String phone;

    @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES)
    @Column(name = "email", insertable = false, updatable = false)
    private String email;

    //Getters and setters ommited
}

Indexing method:

public void index() throws DAOException {
        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager);

        try {
            fullTextEntityManager.createIndexer(Employee.class).purgeAllOnStart(Boolean.TRUE).optimizeOnFinish(Boolean.TRUE).startAndWait();
            logger.info("Indexing....");
        }
        catch (InterruptedException e) {
            logger.error("Error", e);
            throw new DAOException(e);
        }
}
Was it helpful?

Solution

This doesn't work.

Query query = new WildcardQuery(new Term("*", term));

If you want to search across all fields, you'll either need to create a Term for each field you need to search, and combine them (a DisjunctionMaxQuery is usually best for that):

Query query = new DisjunctionMaxQuery(0);
query.add(new TermQuery(new Term("field1", term)));
query.add(new TermQuery(new Term("field2", term)));
query.add(new TermQuery(new Term("field3", term)));

MultiFieldQueryParser is another good tool for this.

Alternatively, a useful pattern is to add all searchable fields into one unstored catch-all field at index time, and when you want to match against anything in the index, you could just query that field instead of enumerate subqueries on all searchable fields.

Also, it looks like you want to add the wildcard to the query here, but you haven't done so. WildcardQuery won't assume any wildcards that aren't there in the term.

Query query = new WildcardQuery(new Term("field", term + "*"));

Since you just need a trailing wildcard, though, I would just use PrefixQuery, which is the standard way of handling a trailing wildcard.

Query query = new PrefixQuery(new Term("field", term));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top