Search API
In this article you'll learn everything you need to know in order to start searching for data in Ucommerce.
Search and indexing basic
In Ucommerce the main data store for editing data is SQL server. Every piece of data you'll edit ends up there. However this data store is not suited for presenting data on the front end for your visitors. For this purpose all catalog data you'll need to show for your visitors will be indexed in a read-fast pre-optimized data store. This data store is pluggable and transparent for the API so at this point it is not really important which one this is. The important thing to keep in mind is there'll be a process for how data is edited and how it can then later be indexed and presented in an optimized way.
The Search API allows you to access and search for indexed data. The most usual search capabilities you'd expect is possible.
The Search API has been designed with simplicity in mind. It will look very similar to LINQ but has been slimmed down to only allow simple search conditions.
Search API
To be able to search you need to resolve the indexed data you want to access. For example if you want to search for products, you resolve the matching index like so.
Ucommerce.Search.IIndex<Ucommerce.Search.Models.Product> productIndex = Ucommerce.Infrastructure.ObjectFactory.Instance.Resolve<Ucommerce.Search.IIndex<Ucommerce.Search.Models.Product>>();
Once you have the right index to start querying it you'll typically use the Find method. This can either query and return the default Product model or your own projection.
ISearch<Ucommerce.Search.Models.Product> query = productIndex.Find(); ISearch<MyProjection> queryWithMyOwnProjection = productIndex.Find<MyProjection>();
Filtering
The ISearch interface allows you to narrow down what you need in a LINQ-like fashion. The following things are possible using the search interface
Ucommerce.Search.Facets.FacetDictionary facetDictionary = new Ucommerce.Search.Facets.FacetDictionary(); facetDictionary["color"] = new [] { "red", "blue" }; query .Where(x => x.Sku == "something") .Where(facetDictionary) .Skip(100) .Take(100);
Full text, Literal, Fuzzy, Wildcard and Range Search
If you want to see some of the capabilities of the ISearch interface, including full text search, you can follow the video below:
- Full Text will search for any occurrences of the word. This can be especially useful for product Description searching.
- Literal will search for any occurrences where the searchterm is identical to the Matched element. This can be especially useful for product SKU searching.
- Fuzzy search will give the searchTerm a distance of incorrect characters. This is useful for mistyping searches, or for converting capital starting letters to non-capital letters.
- Wildcard search gives you the possibility of using * to decide which side you want to extend the search. Eg. Bird* can find products with names such as Birdcage, Birdhat, Birdman etc.
var searchTerm = "something"; query.Where(product => product.LongDescription == Ucommerce.Search.Match.FullText(searchTerm) || product.Sku == Ucommerce.Search.Match.Literal(searchTerm) || product.Name == Ucommerce.Search.Match.Fuzzy(searchTerm, 2) || product.DisplayName == Ucommerce.Search.Match.Wildcard($"*{searchTerm}*"));
- Range search allows you to search for a range of possibilities. This could be either DateTime, Prices, Decimals or IDs.
var lowerLimit = 0m; var upperLimit = 100m; query.Where(product => product.PricesInclTax["EUR 15 pct"] == Ucommerce.Search.Match.Range(lowerLimit, upperLimit));
Sorting
You can sort by any property in the index. You can do this either ascending or descending. See the examples below
query .Where(x => x.Sku == "something") .OrderBy(x => x.Name) .OrderByDescending(x => x["EUR 15 pct"]) //Or descending you can even index into any dynamic property / price property or similar .Skip(100) .Take(100);
Please be aware to sort first, then use skip / take and lastly call ToList() to make sure all operations happen on the full index rather than what you loaded into memory.
Results
Just like LINQ you can keep narrowing your search until you're happy and then ask for a specific result. Until you do so - just like LINQ, you're not punished by performance as all queries are deferred executed. The following capabilities are possible:
Please be aware that calling ToList() should most likely be the last operation you do on your query. Otherwise you may end up getting unexpected results from your skip/take and/or sorting. For example if you sort after ToList() you'll sort in memory instead of in the index meaning that the next page of result you load will be out of sync with what you just sorted.
Ucommerce.Search.ResultSet<Product> result = query.ToList(); var resultWithFacets = query.ToFacets(); int count = query.Count(); Product firstProduct = query.First(); Product firstOrDefaultProduct = query.FirstOrDefault(); Product singleProduct = query.Single(); Product singleOrDefaultProduct = query.SingleOrDefault();
Please note from the example above that you can get a result with and without facets. In case you do not need them, save yourself some MS and stick to the ToList() method.
Total Count and Query Count
After narrowing your search and getting a list of results, you may be interested in showing how many total products exists in the system. This can be done with the following code snippet, where total count and query count gives you the amount of products queried versus the total amount of products in the index.
var totalCount = result.TotalCount; var querycount = result.Results.Count;