Searching Multi-Node Tree Picker data (or any collection) with Examine
The problem is there is a catch, if you’re using the CSV storage (which you must if you’re working with Examine) you’ll hit a problem, the Examine index will have something like this:
1011,1231,1232,1225
But how do you search on that? Searching for ‘1231’ will not return anything, because it’s prefixed with ‘,’ and postfixed with ‘,’. So this brings a problem, how do you search?
Bring on Events
As Shannon spoke about at CodeGarden 10 Examine has a number of different events you can hook into to do different things (slides and code) and this is what we’re going to need to work with.
I’ve touched on events before but this time we’re going to look at a different event, we’re going to look at the GatheringNodeData event.
GatheringNodeData event
So this event in Examine is fired while Examine is scraping the data out of an XML element which it has received. This XML could be from Umbraco (in the scenario we’re looking at here) or it could be from your own data source, and the event is raised once Examine as turned the XML into a Key/ Value representation of it.
The event that raises has custom event arguments, which has a property called Fields. This Fields property is a dictionary which contains the full Key/ Value representation of the data which will end up in Examine!
Now this dictionary is able to be manipulated, so you can add/ remove data as you see if (but that’s a topic for another blog), it also means you can change the data!
Changing the data for our needs
As I mentioned at the start of this we end up with comma-separated string from the datatype which isn’t useful for searching, so we can use an event handler to change what we’ve got. First we need to tie an event handler
public class ExamineEvents : ApplicationBase { public ExamineEvents() { var indexer = ExamineManager.Instance.IndexProviderCollection["MyIndexer"]; indexer.GatheringNodeData += new EventHandler(GatheringNodeDataHandler); } void GatheringNodeDataHandler(object sender, IndexingNodeDataEventArgs e) { //do stuff here } }
So this is just a simple wire-up, using the ApplicationBase class in Umbraco so that it’ll be created on application start-up. Next we need to implement the event handler:
void GatheringNodeDataHandler(object sender, IndexingNodeDataEventArgs e) { //grab the current data from the Fields collection var mntp = e.Fields["TreePicker"]; //let's get rid of those commas! mntp = mntp.Replace(",", " "); //now put it back into the Fields so we can pretend nothing happened! e.Fields["TreePicker"] = mntp; }
And you’re done! Now the data will be written into the index with spaces rather than commas meaning that you can search on each ID without the need for wildcards or any other “hacks” to get it to work.
Note: This will work in the majority of cases, the only reason it’ll fail is if you’re using an analyzer that strips out numbers before indexing. For more information about Lucene analyzers take a look at this article: http://www.aaron-powell.com/lucene-analyzer