Полиморфные запросы с помощью NHibernate Search - PullRequest
2 голосов
/ 07 февраля 2012

У меня есть несколько сущностей, хранящихся в одном индексе поиска NHibernate, в надежде, что я смогу выполнить запрос по всем из них одновременно. Вариант использования - это простая страница поиска, которая возвращает смешанные результаты. Так, например, код может выглядеть так:

public interface ISearchable {}

[Indexed(Index = "TheIndex")]
public class SearchableEntityA : ISearchable
{
    // Some [Field]s
}

[Indexed(Index = "TheIndex")]
public class SearchableEntityB : ISearchable
{
    // Some other [Field]s
}

Это все индексы в порядке, и, конечно, можно запросить в необработанном NHibernate, например:

session.CreateCriteria<ISearchable>().List<ISearchable>();

У меня есть некоторые поля в ISearchable, но они не указаны в привязках NHibernate.

Моя надежда заключалась в том, что я мог просто сказать:

var query = "some keyword";
fullTextSession.CreateFullTextQuery<ISearchable>(query).List<ISearchable>();

И получить список ISearchables, содержащий результаты различных различных объектов. Однако реальность такова, что он выбрасывает NHibernate.HibernateException: Not a mapped entity: NetComposites.Model.ISearchable.

Итак, как проще всего добиться чего-то похожего на полиморфные запросы с помощью NHibernate Search?

1 Ответ

2 голосов
/ 08 февраля 2012

Существует перегрузка CreateFullTextQuery, которая позволяет указывать типы для поиска:

fullTextSession.CreateFullTextQuery(query, typeof(EntityA), typeof(EntityB)).List<ISearchable>();

Немного неуклюже указывать все типы, но они загружаются нормально.Единственная проблема, с которой я столкнулся, заключается в том, что мое предположение о том, что вы можете просто выполнить поиск по всем полям по умолчанию, было неверным, поэтому требуется построить MultiFieldQueryParser по всем свойствам всех доступных для поиска объектов:

private static Query ParseQuery(string query, IFullTextSession searchSession)
{
    var parser = new MultiFieldQueryParser(GetAllFieldNames(searchSession), new StandardAnalyzer());
    return parser.Parse(query);
}

private static string[] GetAllFieldNames(IFullTextSession searchSession)
{
    var reader =
        searchSession.SearchFactory.ReaderProvider.OpenReader(
            searchSession.SearchFactory.GetDirectoryProviders(typeof (Company)));
    var fieldNames = reader.GetFieldNames(IndexReader.FieldOption.ALL);
    return fieldNames.Cast<string>().ToArray();
}
...