2012-02-07 1 views
2

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

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?

ответ

2

Перегрузка 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(); 
}