Adam James
Adam James

Reputation: 4191

Can you sort and search on same field with Hibernate/Lucene?

I have the following annotated class that I am trying to sort the results from a lucene/hibernate search query. I finally have the query working properly but it seems that when I implement the necessary annotations (seen on jobStatus) to sort that column, it makes it impossible to then search that column. I am basing this off the instructions I found here on google. I have been having issues figuring this whole hibernate search and sort thing out, now that I finally figured out how to sort and search all I need is to be able to do them together.

@Entity
@Table(name="jobReq")
@Indexed
public class JobReq {

@Id
@DocumentId
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;

@Field(index = Index.YES)
@Column(name="jobId", nullable=false, unique=true)
private String jobId;

@Field(index = Index.YES)
@Column(name="jobTitle", nullable=false)
private String jobTitle;

@Field(index = Index.YES)
@Column(name="jobContract", nullable=false)
private String contract;

@Field(index = Index.YES)
@Column(name="jobProject", nullable=true)
private String project;

@Field(index = Index.YES)
@Column(name="jobLaborCategory", nullable=false)
private String laborCategory;

@Field(index = Index.YES)
@Column(name="jobSummary", nullable=false)
private String summary;

@Field(index = Index.YES)
@Column(name="jobDescription", nullable=false)
private String jobDescription;

@Fields({@Field, @Field(analyze  = Analyze.NO, name = "jobStatus")})
@Column(name="jobStatus", nullable=false)
private String status;

@Field(index = Index.YES)
@Column(name="TTONumber", nullable=false)
private String TTONumber;

@Field(index = Index.YES)
@Column(name="jobPostedDate", nullable=false)
@Type(type="date")
private Date postedDate;

And a snippet from the search function

Field[] allFields = this.type.getDeclaredFields();
SortField field =new SortField(sortColumn, SortField.STRING, reverseSort);
Sort sort = new Sort(field);
hibQuery = fullTextSession.createFullTextQuery(bq, this.type).setSort(sort);
results = hibQuery.list();

Upvotes: 4

Views: 4774

Answers (3)

Ujjwal Pathak
Ujjwal Pathak

Reputation: 686

Hibernate search documentation provides a solution to this problem similar to Adam's solution.

https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#fields-annotation

Basically use two @Field annotation to index a field twice once with Analyze.NO for sorting and once with Analyze.YES for searching.

@Entity
@Indexed(index = "Book")
public class Book {

    @Field
    @Field(name = "summary_forSort", analyze = Analyze.NO, store = Store.YES)
    @SortableField(forField = "summary_forSort")
    public String getSummary() {
        return summary;
    }

    // ...
}

analyze: determines whether the property is analyzed (Analyze.YES) or not (Analyze.NO). The default value is Analyze.YES.

Tip
Whether or not you want to analyze a property depends on whether you wish to search the element as is, or by the words it contains. It make sense to analyze a text field, but probably not a date field.

Tip
Fields used for sorting or faceting must not be analyzed.

Upvotes: 5

Adam James
Adam James

Reputation: 4191

Turns out you cannot sort and search on the same field, that article from the hibernate book was a tad misleading. So as for a fix I found a solution on the hibernate forums in that you create a 'shadow' column that is a duplicate, one is annotated for searching while the other is annotated for sorting.

It took me a while to find this solution mostly because the answer seems a bit 'hack-y' though fairly straight forward and simple, duplicating data has always been a no-no in my training. But then again I guess you learn something new everyday.

Upvotes: 3

Jason C
Jason C

Reputation: 40336

Two things:

  1. Creating indexes on every column may hurt performance down the line, as index updates are not free. It can also use an unnecessary amount of extra storage space. Of course, if this isn't actually a bottleneck for you, it doesn't matter.

  2. You can sort with Hibernate Criteria, e.g.:

    Criteria c = session.createCriteria(MyObject.class).addOrder(Order.desc(sortColumn));
    Query q = session.createFullTextQuery(bq).setCriteriaQuery(c);
    

    The sort key columns do not need to be indexed.

Upvotes: 1

Related Questions