Reputation: 2503
I have multiple entities stored in a single NHibernate Search index, in the hope that I'd be able to query over all of them at once. The use case is a simple search page which returns mixed results. So, for example, the code could look like this:
public interface ISearchable {}
[Indexed(Index = "TheIndex")]
public class SearchableEntityA : ISearchable
{
// Some [Field]s
}
[Indexed(Index = "TheIndex")]
public class SearchableEntityB : ISearchable
{
// Some other [Field]s
}
This all indexes fine, and of course is queryable in raw NHibernate like so:
session.CreateCriteria<ISearchable>().List<ISearchable>();
I have some fields on ISearchable, but these aren't specifically referenced in NHibernate mappings.
My hope was that I could just say:
var query = "some keyword";
fullTextSession.CreateFullTextQuery<ISearchable>(query).List<ISearchable>();
And retrieve a list of ISearchables, containing results from various different entities. However, the reality is that it throws NHibernate.HibernateException: Not a mapped entity: NetComposites.Model.ISearchable
.
So, what's the simplest way to achieve something resembling polymorphic queries with NHibernate Search?
Upvotes: 2
Views: 516
Reputation: 2503
An overload of CreateFullTextQuery
exists that allows you to specify the types to search:
fullTextSession.CreateFullTextQuery(query, typeof(EntityA), typeof(EntityB)).List<ISearchable>();
It's a little clunky having to specify all the types, but they load fine. The only remaining problem I have is that my assumption that you could just do an all fields search by default was incorrect, so it requires building a MultiFieldQueryParser
over all properties of all searchable entities:
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();
}
Upvotes: 2