Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Fluent Search API
Examine offers a fluent search API which aims to make constructing complex searches simple. The underlying API is determined by the provider implementation, with Examine just exposing the appropriate methods.
An example of the fluent API in action is as follows:
ISearchCriteria sc = ExamineManager.Instance.CreateSearchCriteria( IndexTypes.Content /* type of index to query */); IBooleanOperation query = sc.NodeName("Examine").And().Range("createdDate", new DateTime(2010, 03, 21), // will match all nodes which have the name Examine created between the 21st and the 31st March 2010). new DateTime(2010, 03, 31); IEnumerable<SearchResult> results = ExamineManager.Instance.Search( query.Compile(), /* prepares the query to be handled by the searcher /* 100 /* optional max record count */);
The fluent API has the following methods:
Which can then be joined together using:
See Grouped Operations docs for details on the
The ISearchCriteria interface is the real workhorse of the API, it’s the first interface you start with, and it’s the last interface you deal with. In fact, ISearchCriteria implements IQuery, meaning that all the query operations start here.
In addition to query operations there are several additional properties for such as the maximum number of results and the type of data being searched.
Because ISearchCriteria is tightly coupled with the BaseSearchProvider implementation it is actually created via a factory pattern, like so:
ISearchCriteria searchCriteria = ExamineManager.Instance.SearchProviderCollection["MySearcher"].CreateSearchCriteria(100, IndexType.Content);
What we’re doing here is requesting that our BaseSearchProvider creates an instance of an ISearchCriteria. It takes two parameters:
- int maxResults
- Examine.IndexType indexType
This data can/ should be then used by the search method to return what’s required.
The IQuery interface is really the heart of the fluent API, it’s what you use to construct the search for your site. Since Examine is designed to be technology agnostic the methods which are exposed via IQuery are fairly generic. A lot of the concepts are borrowed from Lucene.Net, but they are fairly generic and should be viable for any searcher. IQuery contains the non-boolean methods listed above.
You’ve probably noticed the IExamineValue parameter which is passable to a lot of the different methods, methods which take a string, but what is IExamineValue? Well obviously it’s some-what provider dependent, so I’ll talk about it as part of Umbraco Examine, as that’s what I think most initial uptakers will want.
Because Lucene supports several different [term modifiers|http://lucene.apache.org/java/2_3_2/queryparsersyntax.html#Term Modifiers] for text we decided it would be great to have those exposed in the API for people to leverage. For this we’ve got a series of string extension methods which reside in the namespace
So once you add a using statement for that you’ll have the following extension methods:
- public static IExamineValue SingleCharacterWildcard(this string s)
- public static IExamineValue MultipleCharacterWildcard(this string s)
- public static IExamineValue Fuzzy(this string s)
- public static IExamineValue Fuzzy(this string s, double fuzzieness)
- public static IExamineValue Boost(this string s, double boost)
- public static IExamineValue Proximity(this string s, double proximity)
- public static IExamineValue Excape(this string s) All of these return an IExamineValue (which UmbracoExamine internally handles), and it tells Lucene.Net how to handle the term modifier you required.
I wont repeat what is said within the Lucene documentation, I suggest you read that to get an idea of what to use and when. The only exceptions are Escape.
If you’re wanting to search on multiple works together then Lucene requires them to be ‘escaped’, otherwise it’ll (generally) treat the space character as a break in the query. So if you wanted to search for Umbraco Rocks and didn’t escape it you’d match on both Umbraco and Rocks, where as when it’s escaped you’ll then match on the two words in sequence.
IBooleanOperation allows your to join multiple IQuery methods together using:
- IQuery And()
- IQuery Or()
- IQuery Not()
These are then translated into the underlying searcher so it can determine how to deal with your chaining. At the time of writing we don’t support nested conditionals (grouped OR’s operating like an And). Each operator will then return an IQuery which will allow you to chain another query method into it.
There’s another method on IBooleanOperation which doesn’t fall into the above, but it’s very critical to the overall idea:
The Compile method will then return an ISearchCriteria which you then pass into your searcher. It’s expected that this is the last method which is called and it’s meant to prepare all search queries for execution. The reason we’re going with this rather than passing the IQuery into the Searcher is that it means we don’t have to have the max results/ etc into every IQuery instance, it’s not something that is relevant in that scope, so it’d just introduce code smell, and no one wants that.
var sc = ExamineManager.Instance.CreateSearchCriteria(); var query = sc.NodeName("umbraco").And().Field("bodyText", "is awesome".Escape()).Or().Field("bodyText", "rock".Fuzzy()); var results = ExamineManager.Instance.Search(query.Compile());