Skip to content
Steve Temple edited this page Jul 9, 2021 · 13 revisions

*** This is Legacy documentation *** here's the links to the current docs:

Tip: There are many unit tests in the source code that can be used as Examples of how to do things. There is also a test web project that has plenty of examples of how to configure indexes and search them.


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 */); 

Methods

The fluent API has the following methods:

Id, NodeName, NodeTypeAlias, ParentId, Field, Range, GroupedAnd, GroupedOr, GroupedNot

Which can then be joined together using:

And, Or, Not

See Grouped Operations docs for details on the Grouped methods

ISearchCriteria

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.

IQuery

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.

IExamineValue

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 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

UmbracoExamine.SearchCriteria

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 fuzziness)
  • public static IExamineValue Boost(this string s, double boost)
  • public static IExamineValue Proximity(this string s, double proximity)
  • public static IExamineValue Escape(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.

Escape

If you’re wanting to search on multiple words 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

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:

ISearchCriteria Compile()

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.

Example:

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());