lucene 使用关键字作为字段名对HashMap进行索引,Hibernate搜索

5kgi1eie  于 2022-11-07  发布在  Lucene
关注(0)|答案(1)|浏览(193)

我想通过使用map键作为字段名来索引map<String, Integer>。我发现默认情况下我只能索引键或值(BuiltinContainerExtractors.MAP_KEY/MAP_VALUES),所以我尝试实现我自己的binder/bridge。这是我的代码:

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后出现异常

1wnzp6jl

1wnzp6jl1#

正如错误消息所告诉您的:
如果这个路径指向暂时性属性,请使用@IndexingDependency(derivedFrom =...)来指定它是从哪些保存的属性衍生而来。如需详细信息,请参阅指涉文件。
具体请参见本节。
简而言之,将注解添加到getRelated(),以便Hibernate搜索知道您从哪些属性派生Map:

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中明确指定 * 整个map* 是“派生的”,而不仅仅是值(正如您所注意到的,这是Hibernate Search默认的目标)。这实际上告诉Hibernate搜索“这个元数据应用于整个Map,而不仅仅是值”。

相关问题