微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在休眠搜索中查询空集合

如何解决如何在休眠搜索中查询空集合

我们正在使用带有 ES 后端的休眠搜索父类有多个不同子对象的集合。我们可以根据子项的值过滤父项,因为集合使用 @IndexedEmbedded 进行注释。

我们希望能够根据子项集合是否为空来过滤父项。我们尝试使用 @IndexedEmbedded(indexnullAs = "null"),然后过滤 queryBuilder.phrase().onField("parent.children").sentence("null").createquery(),这没有任何区别。使用 ES 控制台,我们可以显示父级,但是当集合为空时,它根本没有列出,导致我们认为它没有被索引,因为它是空的。

另一种选择是使用通配符过滤 parent.collection.field,但由于性能原因,hibernate 搜索文档不建议这样做。

解决方法

如果您升级到 Hibernate Search 6,您将能够使用 exists predicate

List<MyEntity> hits = Search.session(entityManager)
        .search(MyEntity.class)
        .where(f -> f.matchAll().except(f.exists().field(“parent.children”))
        .fetchHits(20);

那将解决您的问题,然后您就可以开始担心在您的特定情况下的性能

仍在 Hibernate Search 6 中,如果您的测试表明第一个解决方案的性能确实存在问题,我建议在 children 上使用 custom bridge 来索引是否集合是否为空。像这样:

@SuppressWarnings("rawtypes")
public class MyCollectionEmptyBridge implements ValueBridge<Collection,Boolean> {
    @Override
    public Boolean toIndexedValue(Collection value,ValueBridgeToIndexedValueContext context) {
        return value == null || value.isEmpty();
    }
}

public class MyParentEntity {

   // ...

   @GenericField( 
            name = "childrenAreEmpty",valueBridge = @ValueBridgeRef(type = MyCollectionEmptyBridge.class),// Apply the bridge directly to the collection and not to its elements
            // See https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#_disabling_container_extraction
            extraction = @ContainerExtraction(extract = ContainerExtract.NO) 
    )
    private List<Child> children = new ArrayList<>();

}

List<MyEntity> hits = Search.session(entityManager)
        .search(MyEntity.class)
        .where(f -> f.match().field(“parent.childrenAreEmpty”).matching(true))
        .fetchHits();

第二个解决方案也可以通过 Hibernate Search 5 实现,尽管 Hibernate Search 5's custom bridges 有点难以使用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。