无法在@OneToMany 关联中休眠搜索排序?
Can't hibernate search sort in @OneToMany association?
我尝试按订购日期为客户排序项目列表。日期只能通过 Item.orderPositions.order.orderDate 获得。但是 @IndexedEmbedded 不起作用。没有异常或错误,但结果仅按 HS 逻辑排序。
@Entity
@Indexed
public class Item{
@Id
private long id;
@Field(index = Index.YES, store = Store.YES, analyse = Analyse.YES, analyser = @Analyzer(definition = Constant.ANALYSER))
private String description;
@OneToMany(mappedBy = "item")
@IndexedEmbedded
private List<OrderPosition> orderPositions;
@ManyToOne
@IndexedEmbedded
private Company company;
//getter&setter
}
@Entity
public class OrderPosition{
@Id
private long id;
@ManyToOne
private Item item;
@ManyToOne
@IndexedEmbedded
private Order order;
//getter&setter
}
@Entity
public class Order{
@Id
private long id;
@ManyToOne
private Customer customer;
@Field(index = Index.NO, store = Store.NO, analyze = Analyze.NO)
@SortableField
private String orderDate;
//getter&setter
}
@Entity
public class Company{
@Id
private long id;
@Field(index = Index.NO, store = Store.NO, analyze = Analyze.NO)
@SortableField
private String name;
//getter&setter
}
如果我按项目对列表进行排序。company.name 它工作正常。
queryService.buildFullTextQuery("searchText", Item.class, "description", "company.name").getResultList();
如果我按项目对列表进行排序。orderPosition.order.orderDate 它是默认排序的(HS 逻辑)
queryService.buildFullTextQuery("searchText", Item.class, "description", "orderPositions.order.orderDate").getResultList();
我以这种方式构建 FullTextQuery:
public FullTextQuery buildFullTextQuery(@NonNull String searchText, @NonNull Class<?> clazz, @NonNull String... fields) throws Exception {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(clazz).get();
Query query = qb.keyword().onField(fields[0]).matching(searchText).createQuery();
SortField sortField = new SortField(fields[1], SortField.Type.STRING, false);
Sort sort = new Sort(sortField);
return fullTextEntityManager.createFullTextQuery(query, clazz).setSort(sort);
}
我认为 HS 找不到@OneToMany 的关联。有没有办法解决这个问题?
提前致谢
如果没有您的查询结果,我无法告诉您到底发生了什么,但您肯定在这里做错了什么:您正在尝试对多值字段进行排序。一个项目链接到多个订单,每个订单都有自己的日期。所以每个项目有多个日期。
当您要求比较两个项目,每个项目都有三个日期时,Hibernate Search 应该做什么?只比较最近的日期?只比较最早的日期?你没有说,所以你的查询绑定到 return 个排序不一致的结果。
事实是,没有办法告诉 Hibernate Search 在多值字段中选择哪个值,所以最简单的方法是显式创建一个单值字段进行排序。
例如,您可以在 Item
上添加 getter 到 return 最新订单,并在其中添加 @IndexedEmbedded
:
@Entity
@Indexed
public class Item{
@Id
private long id;
@Field(index = Index.YES, store = Store.YES, analyse = Analyse.YES, analyser = @Analyzer(definition = Constant.ANALYSER))
private String description;
@OneToMany(mappedBy = "item")
@IndexedEmbedded
private List<OrderPosition> orderPositions;
@ManyToOne
@IndexedEmbedded
private Company company;
@javax.persistence.Transient
public Order getLatestOrder() {
Order latestOrder;
// ... compute the latest order ...
return latestOrder;
}
//getter&setter
}
然后按 latestOrder.orderDate
排序,你应该不错。
我尝试按订购日期为客户排序项目列表。日期只能通过 Item.orderPositions.order.orderDate 获得。但是 @IndexedEmbedded 不起作用。没有异常或错误,但结果仅按 HS 逻辑排序。
@Entity
@Indexed
public class Item{
@Id
private long id;
@Field(index = Index.YES, store = Store.YES, analyse = Analyse.YES, analyser = @Analyzer(definition = Constant.ANALYSER))
private String description;
@OneToMany(mappedBy = "item")
@IndexedEmbedded
private List<OrderPosition> orderPositions;
@ManyToOne
@IndexedEmbedded
private Company company;
//getter&setter
}
@Entity
public class OrderPosition{
@Id
private long id;
@ManyToOne
private Item item;
@ManyToOne
@IndexedEmbedded
private Order order;
//getter&setter
}
@Entity
public class Order{
@Id
private long id;
@ManyToOne
private Customer customer;
@Field(index = Index.NO, store = Store.NO, analyze = Analyze.NO)
@SortableField
private String orderDate;
//getter&setter
}
@Entity
public class Company{
@Id
private long id;
@Field(index = Index.NO, store = Store.NO, analyze = Analyze.NO)
@SortableField
private String name;
//getter&setter
}
如果我按项目对列表进行排序。company.name 它工作正常。
queryService.buildFullTextQuery("searchText", Item.class, "description", "company.name").getResultList();
如果我按项目对列表进行排序。orderPosition.order.orderDate 它是默认排序的(HS 逻辑)
queryService.buildFullTextQuery("searchText", Item.class, "description", "orderPositions.order.orderDate").getResultList();
我以这种方式构建 FullTextQuery:
public FullTextQuery buildFullTextQuery(@NonNull String searchText, @NonNull Class<?> clazz, @NonNull String... fields) throws Exception {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(clazz).get();
Query query = qb.keyword().onField(fields[0]).matching(searchText).createQuery();
SortField sortField = new SortField(fields[1], SortField.Type.STRING, false);
Sort sort = new Sort(sortField);
return fullTextEntityManager.createFullTextQuery(query, clazz).setSort(sort);
}
我认为 HS 找不到@OneToMany 的关联。有没有办法解决这个问题?
提前致谢
如果没有您的查询结果,我无法告诉您到底发生了什么,但您肯定在这里做错了什么:您正在尝试对多值字段进行排序。一个项目链接到多个订单,每个订单都有自己的日期。所以每个项目有多个日期。
当您要求比较两个项目,每个项目都有三个日期时,Hibernate Search 应该做什么?只比较最近的日期?只比较最早的日期?你没有说,所以你的查询绑定到 return 个排序不一致的结果。
事实是,没有办法告诉 Hibernate Search 在多值字段中选择哪个值,所以最简单的方法是显式创建一个单值字段进行排序。
例如,您可以在 Item
上添加 getter 到 return 最新订单,并在其中添加 @IndexedEmbedded
:
@Entity
@Indexed
public class Item{
@Id
private long id;
@Field(index = Index.YES, store = Store.YES, analyse = Analyse.YES, analyser = @Analyzer(definition = Constant.ANALYSER))
private String description;
@OneToMany(mappedBy = "item")
@IndexedEmbedded
private List<OrderPosition> orderPositions;
@ManyToOne
@IndexedEmbedded
private Company company;
@javax.persistence.Transient
public Order getLatestOrder() {
Order latestOrder;
// ... compute the latest order ...
return latestOrder;
}
//getter&setter
}
然后按 latestOrder.orderDate
排序,你应该不错。