Hibernate Search with AnalyzerDiscriminator - Analyzer вызывается только при создании Entity?

можете вы помочь мне?

Я реализую Hibernate Search для получения результатов глобального поиска на локализованном веб-сайте (содержимое на португальском и английском языках).

Для этого я выполнил шаги, указанные в документации Hibernate Search: http://docs.jboss.org/hibernate/search/4.5/reference/en-US/html_single/#d0e4141

Наряду с конкретной конфигурацией самого объекта я реализовал класс «LanguageDiscriminator», следуя инструкциям в этом документе.

Поскольку я не получаю именно тех результатов, которых ожидал (например, в моей сущности хранится текст «Capuchinho», но когда я ищу «capucho», я не получаю совпадений), я решил попробовать отладить выполнение и попытаться понять, используются ли анализаторы, которые я настроил, вообще.

При создании новой записи для объекта в базе данных я вижу, что вызывается метод «getAnalyzerDefinitionName()» из «LanguageDiscriminator». Отлично. Но этого не происходит, когда я выполняю поиск. Кто-нибудь может объяснить мне, почему?

Я публикую ключевые части моего кода ниже. Большое спасибо за любой отзыв!

Это одна сущность, которую я хочу проиндексировать

@Entity
@Table(name="NEWS_HEADER")
@Indexed
@AnalyzerDefs({
@AnalyzerDef(name = "en",
        tokenizer = @TokenizerDef(factory =     StandardTokenizerFactory.class),
        filters = {
            @TokenFilterDef(factory = LowerCaseFilterFactory.class),
            @TokenFilterDef(factory = SnowballPorterFilterFactory.class, 
                            params = {@Parameter(name="language", value="English")}
            )
        }
),
@AnalyzerDef(name = "pt",
        tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
        filters = {
            @TokenFilterDef(factory = LowerCaseFilterFactory.class),
            @TokenFilterDef(factory = SnowballPorterFilterFactory.class, 
                            params = {@Parameter(name="language", value="Portuguese")}
            )
        }
)
})
public class NewsHeader implements Serializable {

static final long serialVersionUID = 20140301L;

private int         id;
private String          articleHeader;
private String          language;
private Set<NewsParagraph>  paragraphs = new HashSet<NewsParagraph>();

/**
 * @return the id
 */
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
@DocumentId
public int getId() {
    return id;
}
/**
 * @param id the id to set
 */
public void setId(int id) {
    this.id = id;
}
/**
 * @return the articleHeader
 */
@Column(name="ARTICLE_HEADER")
@Field(index=Index.YES, store=Store.NO)
public String getArticleHeader() {
    return articleHeader;
}
/**
 * @param articleHeader the articleHeader to set
 */
public void setArticleHeader(String articleHeader) {
    this.articleHeader = articleHeader;
}
/**
 * @return the language
 */
@Column(name="LANGUAGE")
@Field
@AnalyzerDiscriminator(impl=LanguageDiscriminator.class)
public String getLanguage() {
    return language;
}
...
}

Это мой класс LanguageDiscriminator

public class LanguageDiscriminator implements Discriminator {

@Override
public String getAnalyzerDefinitionName(Object value, Object entity, String field) {

    String result = null;

    if (value != null) {
        result = (String) value;
    }
    return result;
}

}

Это мой метод поиска, присутствующий в моем SearchDAO.

public List<NewsHeader> searchParagraph(String patternStr) {

    Session session = null;

    Transaction tx;

    List<NewsHeader> result = null;

    try {
        session = sessionFactory.getCurrentSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);
        tx = fullTextSession.beginTransaction();

        // Create native Lucene query using the query DSL
        QueryBuilder queryBuilder = fullTextSession.getSearchFactory()
            .buildQueryBuilder().forEntity(NewsHeader.class).get();

        org.apache.lucene.search.Query luceneSearchQuery = queryBuilder
            .keyword()
            .onFields("articleHeader", "paragraphs.content")
            .matching(patternStr)
            .createQuery();

        // Wrap Lucene query in a org.hibernate.Query
        org.hibernate.Query hibernateQuery = 
            fullTextSession.createFullTextQuery(luceneSearchQuery, NewsHeader.class, NewsParagraph.class);

        // Execute search
        result = hibernateQuery.list();

    } catch (Exception xcp) {
        logger.error(xcp);
    } finally {

        if ((session != null) && (session.isOpen())) {
            session.close();
        }
    }
    return result;
}

person Eduardo Mendes    schedule 05.03.2014    source источник


Ответы (1)


When creating a new record for the entity in the database, I can see that the "getAnalyzerDefinitionName()" method from the "LanguageDiscriminator" gets called. Great. But the same does not happen when I execute a search. Can anyone explain me why?

Выбор анализатора зависит от состояния данного объекта, в вашем случае NewsHeader. Вы имеете дело с экземплярами сущностей во время индексации. Во время запроса у вас нет сущностей для начала, вы ищете их. Какой анализатор Hibernate Search выбрать для своего запроса?

Тем не менее, я думаю, что в DSL есть недостаток. Он не позволяет вам явно указать анализатор для класса. Есть ignoreAnalyzer, но это не то, что вам нужно. Я думаю, вы могли бы создать запрос функции в средстве отслеживания проблем поиска — https://hibernate.atlassian.net/browse/HSEARCH.

Тем временем вы можете создать запрос, используя собственный API запросов Lucene. Однако вам нужно будет знать, на какой язык вы ориентируетесь в своем запросе (например, через предпочтительный язык вошедшего в систему пользователя или что-то еще). Это будет зависеть от вашего варианта использования. Возможно, вы ищете не ту функцию для начала.

person Hardy    schedule 05.03.2014
comment
Спасибо Харди. Мне кажется немного странным, что мы можем выбирать, какие Анализаторы использовать с поиском в Hibernate, но только для целей индексации, а не для выполнения самого поиска. Я попробую то, что вы предлагаете, и попытаюсь выполнить поиск через Lucene API. - person Eduardo Mendes; 06.03.2014
comment
@EduardoMendes У меня точно такая же проблема. Вы решили это до сих пор, кроме использования lucene API? Вы заполнили функцию reauest? ТИА! - person Emi; 18.08.2014