【问题标题】:Index HashMap using keys as fields names. HibernateSearch使用键作为字段名称的索引 HashMap。休眠搜索
【发布时间】:2021-07-26 15:11:34
【问题描述】:

我想通过使用映射键作为字段名来索引map<String, Integer>。我发现默认情况下我只能索引键或值(BuiltinContainerExtractors.MAP_KEY/MAP_VALUES),所以我正在尝试实现自己的活页夹/桥接器。那是我的代码:

public class SomeEntity {

    @Transient
    @PropertyBinding(binder = @PropertyBinderRef(type = ConceptDistancePropertyBinder.class))
    public Map<String, Integer> getRelated() {
        return ...;
    }
}

public class ConceptDistancePropertyBinder implements PropertyBinder {
    @Override
    public void bind(PropertyBindingContext context) {
        context.dependencies().useRootOnly();
        IndexSchemaElement schemaElement = context.indexSchemaElement();
        IndexSchemaObjectField conceptDistanceField = schemaElement.objectField("conceptDistance");
        conceptDistanceField.fieldTemplate(
                "conceptDistanceTemplate",
                fieldTypeFactory -> fieldTypeFactory.asString().analyzer("default")
        );
        final ConceptDistancePropertyBridge bridge = new ConceptDistancePropertyBridge(conceptDistanceField.toReference());
        context.bridge(Map.class, bridge);
    }
}


public class ConceptDistancePropertyBridge implements PropertyBridge<Map> {

    private final IndexObjectFieldReference conceptDistanceFieldReference;

    public ConceptDistancePropertyBridge(IndexObjectFieldReference conceptDistanceFieldReference) {
        this.conceptDistanceFieldReference = conceptDistanceFieldReference;
    }

    @Override
    public void write(DocumentElement target, Map bridgedElement, PropertyBridgeWriteContext context) {
        Map<String, Integer> relatedDistanceWithOtherConcepts = (Map<String, Integer>) bridgedElement;
        DocumentElement indexedUserMetadata = target.addObject(conceptDistanceFieldReference);
        relatedDistanceWithOtherConcepts
                .forEach((field, value) -> indexedUserMetadata.addValue(field, field));
    }
}

我有一个例外:

    Hibernate ORM mapping: 
    type 'com.odysseusinc.prometheus.concept.entity.ConceptEntity': 
        failures: 
          - HSEARCH800007: Unable to resolve path '.related' to a persisted attribute in Hibernate ORM metadata. If this path points to a transient attribute, use @IndexingDependency(derivedFrom = ...) to specify which persisted attributes it is derived from. See the reference documentation for more information.

context.dependencies().useRootOnly() 没有帮助。我也尝试使用context.dependencies().use("somefield"),但遇到了另一个异常

    Hibernate ORM mapping: 
    type 'com.odysseusinc.prometheus.concept.entity.ConceptEntity': 
        path '.related': 
            failures: 
              - HSEARCH700078: No readable property named 'filedName' on type 'java.lang.Integer'

我提取了所有必要的代码并将其放在 GitHub https://github.com/YaroslavTir/map-index 这真的很简单,并且在启动Application.main之后出现异常@

【问题讨论】:

  • "没有名为 'filedName' 的可读属性":只是检查一下:filedName 看起来像是一个错字 - 应该是 fieldName
  • @andrewjames 感谢您的重播。这是一个错字,但它不会改变情况,我也得到了同样的例外,没有错字。

标签: spring lucene hibernate-search hibernate-search-6


【解决方案1】:

正如错误消息告诉你的那样:

如果此路径指向瞬态属性,请使用 @IndexingDependency(derivedFrom = ...) 指定它源自哪些持久属性。有关详细信息,请参阅参考文档。

具体见this section

简而言之,将注解添加到 getRelated() 以便 Hibernate Search 知道您从哪些属性派生了地图:

public class SomeEntity {

    @Transient
    @PropertyBinding(binder = @PropertyBinderRef(type = ConceptDistancePropertyBinder.class))
    @IndexingDependency(
        derivedFrom = {
            @ObjectPath(@PropertyValue(propertyName = "someProperty1")),
            @ObjectPath({@PropertyValue(propertyName = "someProperty2"), @PropertyValue(propertyName = "someNestedProperty")})
        },
        extraction = @ContainerExtraction(extract = ContainerExtract.NO)
    )
    public Map<String, Integer> getRelated() {
        return ...;
    }
}

请注意,在您的情况下,您必须在 @IndexingDependency 中明确指定 整个地图 是“派生的”,而不仅仅是值(这是 Hibernate Search 默认的目标,如你注意到了)。这就是您需要extraction = @ContainerExtraction(extract = ContainerExtract.NO) 的原因:这实际上告诉 Hibernate Search“此元数据适用于整个地图,而不仅仅是值”。

【讨论】:

  • 感谢您这么快的回答。 IndexingDependency 是我尝试的第一件事。这没有帮助。我认为我们应该使用context.dependencies().use 对其进行配置,我编写了一个简单的应用程序来重现它。 github.com/YaroslavTir/map-index
  • @yaroslavTir Right... 这是因为 @IndexingDependency 与任何其他 Hibernate Search 注释一样,默认情况下将针对 .map。您需要将extraction = @ContainerExtraction(extract = ContainerExtract.NO) 添加到@IndexingDependency 以澄清您的意思是整个地图 是派生的。我知道这有点奇怪,但如果你考虑其他一切是如何工作的,那就更有意义了。无论如何,我更新了我的答案。
  • 我创建了HSEARCH-4271,希望能在 Hibernate Search 的未来版本中解决这个问题。
  • ContainerExtract.NO 解决问题,谢谢解答
猜你喜欢
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
相关资源
最近更新 更多