Hibernate Search是否支持嵌套查询、has_child及has_parent查询?
Great question! Let me break down exactly how Hibernate Search handles these query scenarios for you:
1. 嵌套查询的支持
Hibernate Search 完全支持嵌套查询,核心是通过@IndexedEmbedded注解将关联的子实体字段嵌入到父实体的索引中,之后就能针对嵌套字段构建精准查询。
举个实体映射的例子:
@Indexed public class Order { @Id private Long id; @IndexedEmbedded // 将子实体LineItem的字段嵌入到Order的索引中 private List<LineItem> lineItems; // 其他字段、getter/setter省略 } public class LineItem { private String productName; private BigDecimal price; // 其他字段、getter/setter省略 }
要查询所有包含"笔记本电脑"商品的订单,直接通过嵌套路径构建查询即可:
SearchSession searchSession = Search.session(entityManager); List<Order> matchingOrders = searchSession.search(Order.class) .where(f -> f.match("lineItems.productName").matching("笔记本电脑")) .fetchHits(20);
如果需要子实体同时满足多个条件,还可以用nested()查询明确指定嵌套对象范围:
List<Order> matchingOrders = searchSession.search(Order.class) .where(f -> f.nested() .objectField("lineItems") .nest(f -> f.bool(b -> b .must(f.match("lineItems.productName").matching("笔记本电脑")) .must(f.range("lineItems.price").greaterThan(new BigDecimal("5000"))) )) ) .fetchHits(20);
2. 等价于has_child的查询
Hibernate Search没有直接叫has_child的API,但完全能实现它的核心需求:查询包含符合条件子实体的父实体。
其实就是上面嵌套查询的典型场景——只要子实体满足指定条件,对应的父实体就会被返回。比如要找所有包含单价超过1000元商品的订单,用上面的nested()查询就能实现和Elasticsearch原生has_child完全一致的效果。
3. 等价于has_parent的查询
同样,Hibernate Search也没有直接的has_parentAPI,但可以通过实体映射实现查询属于符合条件父实体的子实体的需求。
只需要在子实体中用@IndexedEmbedded嵌入父实体的字段即可:
@Indexed public class LineItem { @Id private Long id; private String productName; private BigDecimal price; @IndexedEmbedded // 将父实体Order的字段嵌入到LineItem的索引中 private Order order; // 其他字段、getter/setter省略 }
现在要找所有属于已发货(SHIPPED)订单的商品条目,直接查询子实体中嵌入的父实体字段:
List<LineItem> matchingItems = searchSession.search(LineItem.class) .where(f -> f.match("order.status").matching("SHIPPED")) .fetchHits(20);
如果父实体是独立索引、没有在子实体中嵌入,也可以用跨类型查询结合关联条件实现,但嵌入父字段的方式通常更高效。
小提示
- 以上示例基于Hibernate Search 6.x(当前稳定主流版本),如果是5.x版本,API写法会略有不同,但核心能力是一致的。
- 务必确保
@IndexedEmbedded配置正确,否则嵌套字段不会被索引,相关查询也就无法生效。
内容的提问来源于stack exchange,提问作者Susanta Mohapatra

