Как использовать @Facet со встроенными объектами?

Я пытаюсь перейти с HS 4 на 5, но у меня проблемы с поиском. Я понимаю, что @Facet нужно добавить в граненые поля и видел это, например. Но граненое поле, которое я хочу использовать, встроено на 2 уровня ниже, и все, что я получаю, это ошибка:

org.hibernate.search.exception.SearchException: HSEARCH000268: Facet request 'ClientId' tries to facet on  field 'scan.clientGroup.id' which either does not exist or is not configured for faceting (via @Facet). Check your configuration.

Я пробовал @Facet во встроенном объекте во многих различных вариантах, но, похоже, ничего не работает - я хотел бы знать, как это настроить, спасибо.

2 ответа

Решение

Решение, которое вы упомянули в своем ответе, является правильным.

Другое решение было бы иметь @IndexedEmbedded от ребенка к родителю, добавьте @Facet непосредственно в свойстве родительского идентификатора, и используйте parent.parentId как имя поля в вашем запросе на фасетирование, как показано в пиаре, который я только что отправил.

Основным преимуществом вашего решения является то, что если Parent сам индексируется (если у него есть собственный индекс), родительский индекс не будет излишне загрязнен ограненным полем (в отличие от моего решения).

Основным недостатком вашего решения является то, что вы по существу объявляете индексированное поле для переходного поля в вашей сущности (переходное в смысле JPA, то есть не отображается непосредственно на столбец базы данных). Это означает, что Hibernate Search не может определить, когда это значение изменится, и в результате Hibernate Search отключит некоторые оптимизации и будет переиндексировать Child сущность всякий раз, когда собственность Child изменения, любые свойства, даже не связанные. Если ваша сущность мала, редко обновляется или имеет ограниченное количество экземпляров, это может не иметь значения. Просто имейте это в виду, если вы заметите много чтений из базы данных, по-видимому, без причины в будущем.

Я нашел решение. Я понятия не имею, если это рекомендуемый способ, возможно, @yrodiere мог бы прокомментировать?

По сути, просто добавьте метод получения в корневую сущность с соответствующей аннотацией @Facet:

@Indexed
@Entity
public class Child {

...

    @ManyToOne
    @IndexedEmbedded(includeEmbeddedObjectId = true)
    Parent parent;

    @Field(analyze = Analyze.NO)
    @Facet(encoding = FacetEncodingType.STRING)
    public Long getParentId() {
        return parent != null ? parent.getId() : null;
    }
}

тогда в запросе:

FullTextQuery fullTextQuery = ftem.createFullTextQuery(luceneQuery);

        FacetingRequest facetingRequest = builder.facet()
                .name("facetRequest")
                .onField("parentId")
                .discrete()
                .orderedBy(FacetSortOrder.COUNT_DESC)
                .includeZeroCounts(false)
                .maxFacetCount(10)
                .createFacetingRequest();

        FacetManager facetManager = fullTextQuery.getFacetManager();
        facetManager.enableFaceting(facetingRequest);

        List<Facet> facets = facetManager.getFacets("facetRequest");

В этом случае мне также пришлось кодировать поле в виде строки, чтобы можно было использовать дискретную огранку, а не диапазон, поскольку по умолчанию это числовое поле.

Другие вопросы по тегам