Issue
I'm using hibernate search(latest release) with a local Lucene backend. I have two entities as follows;
@Entity
@Indexed
public class A {
@Id
private Long id;
@FullTextField
private String text;
@KeywordField
private String keyword;
}
@Entity
public class B {
private BigDecimal number;
@OneToOne
@JoinColumn(name = "a_id")
private A a;
}
I have mass indexer that handles indexing A entities at the application startup. While searching I want search results to be ordered by number field of entity B.
My search function is a simple boolean predicate as follows
.where(f -> f.bool()
.should(f.match().field("text").matching(query))
.should(f.match().field("keyword").matching(query.toUpperCase(Locale.ENGLISH)))
)
.fetch(offset, limit)
What should I do to order/boost search results depending on another field of another entity which has one-to-one relation?
Solution
You're using the word "boost", but I think you're simply after "sorting". "bootsting" is a different concept that affects the score, and only affects the order of hits indirectly.
To sort by this number
property, you will have to embed it into the index document created for A
. To that end, use @IndexedEmbedded
:
@Entity
@Indexed
public class A {
@Id
private Long id;
@FullTextField
private String text;
@KeywordField
private String keyword;
// Add this, and make sure to update it every time you update B.a
@OneToOne(mappedBy = "a")
@IndexedEmbedded
private B b;
}
@Entity
public class B {
private BigDecimal number;
@OneToOne
@JoinColumn(name = "a_id")
private A a;
}
WARNING: Make sure that every time you call b.setA(...)
, you also call a.setB(...)
so that all entities are consistent. Otherwise, Hibernate Search will not be able to index your data properly.
Then annotate number
so that it's indexed and sortable:
@Entity
public class B {
@GenericField(searchable = Searchable.NO, sortable = Sortable.YES)
private BigDecimal number;
@OneToOne
@JoinColumn(name = "a_id")
private A a;
}
Then add a sort to your query:
.where(f -> f.bool()
.should(f.match().field("text").matching(query))
.should(f.match().field("keyword").matching(query.toUpperCase(Locale.ENGLISH)))
)
.sort(f -> f.field("b.number").asc())
.fetch(offset, limit)
Answered By - yrodiere