简体   繁体   English

Hibernate中如何调整索引映射名称搜索6

[英]How to adjust the index mapping name in Hibernate Search 6

We have a few indexed entities that include an address entity in slightly different ways but we want to be able to search on any of these entities using the same mapping path to address fields.我们有一些索引实体,它们以稍微不同的方式包含地址实体,但我们希望能够使用相同的映射路径搜索这些实体中的任何一个到地址字段。

In Hibernate Search 5, it was possible to define the index mapping path explicitly ( @IndexedEmbedded(prefix =...) ) and use dots in the path which solved this issue, but Hibernate Search 6 doesn't support explicit dots in the path.在 Hibernate 搜索 5 中,可以显式定义索引映射路径 ( @IndexedEmbedded(prefix =...) ) 并在解决此问题的路径中使用点,但 Hibernate 搜索 6 不支持路径中的显式点.

Hopefully this example helps to illustrate.希望这个例子有助于说明。 This is pseudo-ish code in transition from HS5 to HS6.这是从 HS5 过渡到 HS6 的伪代码。

@Entity
@DiscriminatorValue("entity1Address")
public class Entity1Address extends AbstractAddress {

    private Entity1 entity1;

    //...
}
    
@Entity
@Table(name = "address")
@DiscriminatorColumn(name = "dtype")
public abstract class AbstractAddress {

    private Address address = new Address();

    @Embedded
    @IndexedEmbedded
    @AttributeOverrides({
            @AttributeOverride(name = "line1", column = @Column(name = "addr_line_1")),
            //..other address fields
    })
    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

@Embeddable
@AccessType("property")
public class Address {

    private String line1;
    //...other address fields

    //... line1 getter & setter
    
    @Transient
    @IndexingDependency(derivedFrom = @ObjectPath(@PropertyValue(propertyName = "line1")))
    //IndexingDependencies for other address lines
    @FullTextField(name = "line", analyzer = ADDRESS_LINE_ANALYZER)
    public List<String> getLines() {
        List<String> lines = Lists.newArrayListWithExpectedSize(4);
        if (StringUtils.hasText(line1)) {
            lines.add(line1);
        }
        //...add other address lines

        return lines;
    }   
}

Now for 2 examples of using addresses:现在看两个使用地址的例子:

@Entity
@Table(name = "entity1")
@Indexed(index = "ENTITY1")
public class Entity1 {
    private Set<Entity1Address> addresses = Sets.newLinkedHashSet();
    
    @OneToMany(mappedBy = "entity1")
    @IndexedEmbedded
    public Set<ClientVendorAddress> getAddresses() {
        return addresses;
    }

    private void setAddresses(Set<EntityAddress> addresses) {
        this.addresses = addresses;
    }   
}

Entity1 has an index mapping path to line1 of "addresses.address.line1" Entity1 具有到“addresses.address.line1”的 line1 的索引映射路径

But Entity2 is where the conflict comes into play b/c it uses address more directly:但是 Entity2 是冲突发挥作用的地方 b/c 它更直接地使用地址:

@Entity
@Table(name = "entity2")
@Indexed(index = "ENTITY2")
public class Entity2 {

    private Address physicalAddress;
    
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "line1", column = @Column(name = "physical_addr_line_1")),
            //...other address fields
    })
    public Address getPhysicalAddress() {
        return physicalAddress;
    }

    public void setPhysicalAddress(Address physicalAddress) {
        this.physicalAddress = physicalAddress;
    }

    @Transient
    @IndexingDependency(derivedFrom = @ObjectPath(@PropertyValue(propertyName = "physicalAddress")))
    //@IndexedEmbedded(prefix = "addresses.address.")  // <--- in HS 5, this is how we standardized the mapping path between Entity1 and Entity2, but HS 6 doesn't support dots in the notation
    @IndexedEmbedded
    public Set<Address> getAddresses() {
        Set<Address> addresses = Sets.newLinkedHashSet();
        
        if (hasPhysicalAddress()) {
            addresses.add(physicalAddress);
        }       
        //...add other addresses
        
        return addresses;
    }
}

Entity2 has an index mapping path to line1 of "addresses.line1", which is not the same as Entity1. Entity2 有“addresses.line1”的line1 的索引映射路径,与Entity1 不同。

There are times we want to search both Entity1 and Entity2 based on the same field mapping, meaning "addresses.address.line1" for both, but we no longer can in HS 6. Or even more common is that the SearchPredicates built are at a much lower level in the code than where the SearchPredicateFactory is created (which is where the entity is supplied) in order to reuse our queries/predicates.有时我们希望基于相同的字段映射同时搜索 Entity1 和 Entity2,这意味着两者都为“addresses.address.line1”,但在 HS 6 中我们不再可以。或者更常见的是构建的 SearchPredicates 位于为了重用我们的查询/谓词,代码中的级别比创建 SearchPredicateFactory 的位置(提供实体的位置)要低得多。

An example of building our predicate:构建我们的谓词的一个例子:

// At some high level, we create the SearchPredicateFactory:
SearchSession searchSession = Search.session(session);
SearchPredicateFactory pf = searchSession.scope(Entity1.class).predicate();

// then much lower, for reuse reasons, we create predicates:
var myBool = pf.bool();
myBool.should(
    pf.match()
        // need a common mapping definition to reach line1 in any entity
        .field(LINE1_FIELD)
        .matching("100 main street")
);

Is there a way to do this through HS 6 configuration?有没有办法通过 HS 6 配置来做到这一点?

In Hibernate Search 5, it was possible to define the index mapping path explicitly (@IndexedEmbedded(prefix =...)) and use dots in the path which solved this issue, but Hibernate Search 6 doesn't support explicit dots in the path.在 Hibernate 搜索 5 中,可以显式定义索引映射路径 (@IndexedEmbedded(prefix =...)) 并在解决此问题的路径中使用点,但 Hibernate 搜索 6 不支持路径中的显式点.

Technically Hibernate Search still supports it (it works), but it's deprecated and not recommended.从技术上讲 Hibernate 搜索仍然支持它(它有效),但它已被弃用且不推荐。

This should work just fine:这应该可以正常工作:

    //@IndexedEmbedded(prefix = "addresses.address.")  // <--- in HS 5, this is how we standardized the mapping path between Entity1 and Entity2, but HS 6 doesn't support dots in the notation

Why don't you explain what doesn't work exactly?你为什么不解释什么不完全有效? An exception?例外? Doesn't behave as expected?表现不如预期?

Is there a way to do this through HS 6 configuration?有没有办法通过 HS 6 配置来做到这一点?

Eventually you'll have more control and will be able to use @IndexedEmbedded programmatically in bridges, but that's not implemented yet.最终,您将拥有更多控制权,并且能够以编程方式在网桥中使用@IndexedEmbedded ,但这还没有实现。 (see the idea of NestedBinding here if you're curious). (如果您好奇,请参阅此处NestedBinding的想法)。

In the meantime, you really should be able to just use @IndexedEmbedded(prefix =...) .与此同时,你真的应该能够只使用@IndexedEmbedded(prefix =...) It's deprecated, but it's not been removed and it should still work, as explained above.如上所述,它已被弃用,但尚未被删除,它应该仍然可以工作。

Alternatively, have you tried just wrapping the addresses of Entity2 into a new class, Entity2Address , which is not mapped in Hibernate ORM (because you don't need to)?或者,您是否尝试将Entity2的地址包装到新的 class Entity2Address中,该地址未映射到 Hibernate ORM 中(因为不需要)?

public class Entity2Address extends AbstractAddress {
    //...
}
@Entity
@Table(name = "entity2")
@Indexed(index = "ENTITY2")
public class Entity2 {

    private Address physicalAddress;
    
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "line1", column = @Column(name = "physical_addr_line_1")),
            //...other address fields
    })
    public Address getPhysicalAddress() {
        return physicalAddress;
    }

    public void setPhysicalAddress(Address physicalAddress) {
        this.physicalAddress = physicalAddress;
    }

    @Transient
    @IndexingDependency(derivedFrom = {
        @ObjectPath(@PropertyValue(propertyName = "physicalAddress"), @PropertyValue(propertyName = "lines")),
        // ... other address fields if necessary ...
    })
    @IndexedEmbedded
    public Set<Entity2Address> getAddresses() {
        Set<Entity2Address> addresses = Sets.newLinkedHashSet();
        
        if (hasPhysicalAddress()) {
            addresses.add(new Entity2Address(physicalAddress));
        }       
        //...add other addresses
        
        return addresses;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM