Searching with taxonomies and containers

Topics: Core, Customizing Orchard, General, Troubleshooting, Writing modules
Oct 29, 2014 at 4:53 PM
Edited Oct 29, 2014 at 4:58 PM
We are working on an Orchard website that uses taxonomies and containers. The top level of our structure is the taxonomy, which is used as a category for items. Then there are main items, which have a taxonomy field and are also a container and thus contain sub-items. Those sub-items can also contain sub-items.

Now we need to make/find find a way to search through all items within a certain category. So the user has to be able to select one of the taxonomies and then enter a normal search term. Then Orchard should search only through all the items that contain the taxonomy and all their sub-items and sub-sub-items.

So for example, we could have a structure like this:
Taxonomy category
-- Cars
---- Ferrari
------ Ferrari model 1
------ Ferrari model 2
---- Volvo
------ Volvo model 1
------ Volvo model 2
-- Food
---- Fruit
------ Apple
------ Banana
---- Meat
------ Pork
------ Chicken
-------- Chicken breast
-------- Chicken wing
"Cars" and "Food" are taxonomy terms and the rest are content items with container/containable. In this example the user should be able to select "food" and search for "wing" or something. Then he would get "Chicken wing" as a search result. If the user searches for "Chicken", he would get the item "Chicken" and also all the subitems that contain the word "chicken". But if the user selects the "Cars" category and search for "wing", he would get no results.
Don't pay attention to the names I used in my example, our project has nothing to do with cars or food, it's just to show he structure.

So what would be the best way to make this? I assume we can do all this with Lucene, but how?
Nov 4, 2014 at 1:18 PM
Edited Nov 4, 2014 at 1:19 PM
We have managed to get something working now, but not the way we would like. What we do now is search for all related items of the taxonomy (including all children etc) and then build our own Lucene query like this:
var booleanQuery = new BooleanQuery();
Analyzer analyzer = new StandardAnalyzer(LuceneIndexProvider.LuceneVersion);

var query = new QueryParser(LuceneIndexProvider.LuceneVersion, "title", analyzer).Parse(q);
var id = new QueryParser(LuceneIndexProvider.LuceneVersion, "id", analyzer).Parse(String.Join(" ", idsToUseInSearch));
booleanQuery.Add(query, Occur.MUST);
booleanQuery.Add(id, Occur.MUST);

searchBuilder.Mandatory();

var lucene = typeof (LuceneSearchBuilder);
lucene.InvokeMember("CreatePendingClause", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, searchBuilder, null);

var field = lucene.GetField("_query", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(field != null);
field.SetValue(searchBuilder, booleanQuery);

searchHits = Query(pager.Page, pager.PageSize, false, searchHit => searchHit, searchBuilder);
This is working fine for us now, but if anyone knows a better way please let me know and we will update our code.