-
Notifications
You must be signed in to change notification settings - Fork 23
Using LINQ
Sitecore 7 introduces new functionality to allow querying search indexes such as Lucene or SOLR using LINQ syntax on strongly typed objects. This opens up many powerful options when using a mapper such as Synthesis.
Note: Synthesis does not currently support SOLR, though it probably will in future.
Synthesis extends the default LINQ query syntax by also allowing querying on interfaces as well as concrete types. This allows us to keep all the decoupled goodness of Synthesis intact even when searching indexes.
There are a lot of things to keep in mind when using LINQ (see this blog post) and they mostly apply when using Synthesis. If you understand how to use the LINQ layer, Synthesis' implementation should make you feel at home. There are some useful abstractions with Synthesis however:
- Synthesis will by default automatically apply sensible filtering to your results:
- Making sure the template of the result is appropriate for the requested Synthesis type
- Limiting results to the current context language only
- Limiting results to the most recent version available
- Synthesis uses a custom object property mapper when interacting with Synthesis item types that is much faster than the default object mapper so it will work decently with larger result sets
Here's a basic example of a Sitecore LINQ query using Synthesis:
using (var context = ContentSearchManager.CreateSearchContext(new SitecoreIndexableItem(Sitecore.Context.Item)))
{
// note using the GetSynthesisQueryable() extension not the usual GetQueryable(), which doesn't support interfaces and won't auto-filter
var searchResults = context.GetSynthesisQueryable<IMountainDetailPageItem>().Where(x => x.Country.RawValue == "USA");
}
You cannot use every property available on field classes to query against the index. Only the property that would logically map to an index field should be used. For example:
- For TextField and RichTextField, use the RawValue property
- For DateTimeField, BooleanField, IntegerField, NumericField, use the Value property
- For querying arbitrary index fields, use the item indexer (e.g.
.Where(x => x["field"] == "value"))
For advanced search scenarios, note that you can attach more than one Where clause to a query and add to the chain of clauses in more than one expression, e.g.
var foo = queryable.Where(x=>x.Name.Contains("hello"));
if(filterOn)
foo = foo.Where(x=>x.Type == "Monkey");
You can use faceting just like a normal Sitecore LINQ query by using the FacetOn extension method (in the Sitecore.ContentSearch.Linq namespace). You should facet on the same field properties you would use for a predicate clause. At present, Synthesis does not provide any facilities to strongly type or translate values in facet results.
It's also suggested that you use the GetResults extension method as the last link in your query chain. This method provides you with additional metadata on top of simply enumerating the IQueryable, such as the facet results and the boost of each result. In future, more result metadata may be added such as abstracts so using the SearchHit<TResult> provided by GetResults makes you ready for later upgrades.
Synthesis will transparently load Sitecore.Data.Item to back your index results if you access a property that is not in the index. This can cause problems if you're relying on the index for speed and unintentionally access a property that causes iterative data access. You can diagnose such situations in a couple ways:
- You can programmatically check what kind of object you have by checking the
InstanceTypeproperty on the Synthesis object. - If you have a debugger attached, item promotions are automatically written to the debug output window