Как сериализовать Set <Entity>как строковый массив в ElasticSearch с помощью Hibernate-Search? - PullRequest
0 голосов
/ 06 октября 2018

Я использую hibernate-search для сопоставления моих сущностей с MySQL и ElasticSearch.

Существует несоответствие между тем, как я хочу, чтобы документы эластичного поиска были проиндексированы, и тем, как они на самом деле индексируются.

У меня есть объект с именем Product с набором ProductImage.Я хотел бы, чтобы ProductImage сущности были сериализованы как массив строк в индексе эластичного поиска.


У меня есть это:

Реляционный мир (MySQL):

> Product table
______________________________
| gtin | price | other_stuff |
------------------------------
> ProductImage table
_______________
| gtin | path |
---------------

Безотносительный мир (индекс Elasticsearch):

http://elasticsearch.domain.com/products/com.example.Product/_search
{
    "gtin" : "1234"
    "images" : [
        { 
            "path" : "http://image.host.com/product-image-1"
        }, 
        { 
            "path" : "http://image.host.com/product-image-2"
        }
    ]
}

Но я хочу этого:

http://elasticsearch.domain.com/products/com.example.Product/_search
{
    "gtin" : "1234"
    "images" : [
        "http://image.host.com/product-image-1",
        "http://image.host.com/product-image-2"
    ]
}

Это моя реализация:

@Entity
@Table(name = "products")
@Indexed(index = "products")
public class Product implements Serializable {

    @Id
    String gtin;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "gtin", referencedColumnName = "gtin")
    @IndexedEmbedded
    Set<ProductImage> images = new TreeSet<>();

}


@Entity
@Table(name = "product_images")
public class ProductImage implements Serializable {

    @EmbeddedId
    @Field
    @FieldBridge(impl = IdBridge.class)
    //@ContainedId <- also tried something with this
    Id id;

    public Id getId() {
        return id;
    }

    public void setId(Id id) {
        this.id = id;
    }

    @Embeddable
    public static class Id implements Serializable {

        String gtin;

        @Field
        //@ContainedId <- also tried something with this
        String path;

        public String getGtin() {
            return gtin;
        }

        public void setGtin(String gtin) {
            this.gtin = gtin;
        }

        public String getPath() {
            return path;
        }

        public void setPath(String path) {
            this.path = path;
        }
    }

    public static class IdBridge implements StringBridge {
        @Override
        public String objectToString(Object object) {
            Id id = (Id) object;
            return id.getPath();
        }
    }

}

Как можно сделать, чтобы индексировать Изображения продуктов какпростой массив строк внутри продукта?

1 Ответ

0 голосов
/ 08 октября 2018

Вам необходимо заменить @IndexedEmbedded на мост.

Определить мост:

public class ProductImageSetPathBridge implements MetadataProvidingFieldBridge {

    @Override
    public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
        builder.field( name, FieldType.STRING );
    }

    @Override
    public void set(String fieldName, Object value, Document document, LuceneOptions luceneOptions) {
        if ( value != null ) {
            indexNotNullIterable( fieldName, value, document, luceneOptions );
        }
    }

    private void indexNotNullIterable(String name, Object value, Document document, LuceneOptions luceneOptions) {
        Iterable<?> collection = (Iterable<?>) value;
        for ( Object entry : collection ) {
            indexEntry( name, entry, document, luceneOptions );
        }
    }

    private void indexEntry(String fieldName, Object entry, Document document, LuceneOptions luceneOptions) {
        ProductImage image = (ProductImage) entry;
        if ( image != null ) {
            luceneOptions.addFieldToDocument( fieldName, image.getId().getPath(), document );
        }
    }

}

И применить его в нужном месте, в классе Product:

@Entity
@Table(name = "products")
@Indexed(index = "products")
public class Product implements Serializable {

    @Id
    String gtin;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "gtin", referencedColumnName = "gtin")
    // Remove this @IndexedEmbedded
    //@IndexedEmbedded
    // And put this instead
    // Don't forget analyze = Analyze.NO, because you probably don't want an URL to be analyzed
    @Field(bridge = @FieldBridge(impl = ProductImageSetPathBridge.class), analyze = Analyze.NO)
    Set<ProductImage> images = new TreeSet<>();

}

Дополнительная информация о мостах:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...