LightSpeed: Writing a custom Search Engine
Tagged as LightSpeedLightSpeed includes the ability to use a custom full text search engine to more quickly and easily query your data in a soft manner. This has proved very helpful and saved many hours of work for website developers when they need to create a site search function.
By default, LightSpeed ships with a Lucene search engine implementation so that you can work with any of the many database engines LightSpeed supports and still get a very high quality, scalable and easy to use search capability.
This post is about helping developers who want to write their own custom search provider. Perhaps you don’t want to use Lucene or, perhaps you just have an existing search product you would like to leverage. LightSpeed makes it easy for you to plug in your own provider.
Configure a search engine
Configuration of the search engine capabilities is done at the LightSpeedContext level. For example, to configure a context to use the built in Lucene Search Engine, you could do the following in code to configure your LightSpeedContext (you can do this also in the application config, please check the help documentation on how to achieve this).
LightSpeedContext.Default.SearchEngine = new SearchEngineBroker(new LuceneSearchEngine()); LightSpeedContext.Default.SearchEngineFileLocation = "c:\searchindex";
Notice that there are two configuration properties for the search engine – the class that will act as the search engine, and the location of the index (if your search engine needs one). When you create your own provider, just plug the class in as the searchEngineClass and you’ll be ready to go!
The ISearchEngine interface
To create a search provider you must create a class that adheres to the ISearchEngine interface. Once a class conforms to this interface it can be assigned in the configuration as the Search Engine you wish to use.
public interface ISearchEngine { IList<SearchResult> Search(string query, params string[] scopes); void Add(IndexKey indexKey, string data); void Update(IndexKey indexKey, string data); void Remove(IndexKey indexKey); void Optimize(); void Clear(); LightSpeedContext Context { get; set; } void BeginBulkAdd(); void EndBulkAdd(); }
But what should these methods do?
Most of these methods are self explanatory and there is significant intellisense support as well as documentation in the help file about this interface but here’s a break down of what each should do:
IList
Perform the actual search and return a collection of SearchResult items with details about the entities discovered. The scopes params collection is a string representation of the types that the user wishes to search over (and passed in as strings because some search repositories, Lucene for example, store everything as a string).
void Add(IndexKey indexKey, string data);
Add a single item to the index. The indexKey is a type that stores information about the scope, entity identity, etc. The data is the content that will be searched over and is a concatenation of the fields marked up as [Indexed] in the entity being added, or the overridden GetSearchData() method on the entity being indexed.
void Update(IndexKey indexKey, string data);
Update a single item in the index.
void Remove(IndexKey indexKey);
Remove a single item in the index.
void Optimize();
Optimize the index. This is useful for search engines that have an optimisation process that can run at the end of a indexing operation. Again, this was borrowed from the Lucene way of operating but if your custom search engine doesn’t have this operation then just don’t do anything in the method.
void Clear();
Reset the search store to an empty state.
LightSpeedContext Context { get; set; }
Manage the context that that this search engine is associated with. This provides access to the configuration of the context (such as the search engine index directory if you use one). LightSpeed will automatically assign the context to the property, so simply storing the value in a local variable is all you need to do.
void BeginBulkAdd();
Some search engines will have a mechanism for opening a search index writer so that it gets held open for bulk add operations. This is called when undertaking options like Rebuild() on the SearchEngineBroker for doing a mass re-creation of the search index.
void EndBulkAdd();
When undertaking a bulk add operation, there is often a need to close an index writing operation.
What’s next?
Have a go at writing a provider for youself! The best way to learn is to code something up yourself. If you’re not interested in writing your own the perhaps experiment with the built in Lucene search engine.
Click here to download a zip of the LuceneSearchEngine.cs (zipped) implementation as a reference for writing you own (but do note, it’s very specific to Lucene, your one will likely look considerably different internally). Let us know if you write one!
One Response to “LightSpeed: Writing a custom Search Engine”
Leave a Reply
Categories
BrainDump (1)
Community Code (4)
Events (16)
F# (14)
General (53)
Lab Samples (2)
LightSpeed (268)
MegaPack (8)
News (71)
NHibernate Designer (26)
Nightly news (53)
Phone Elements (24)
Products (87)
Projects (5)
Screencast (6)
SharePoint (3)
Silverlight (14)
Silverlight Elements (66)
SimpleDB Management Tools (20)
Visual Studio (9)
VS File Explorer (7)
Web Workbench (39)
WPF (44)
WPF Diagrams (57)
WPF Elements (110)
WPF Property Grid (32)



Posted by John-Daniel Trask on 25 February 2009 



I have done an example using Sql Server FTS at http://sourceitsoftware.blogspot.com/2010/01/net-using-sql-server-full-text.html.
This explains some of the tricker points.