How to write Solr query using SolrNet

Hello everyone, in this blog we will learn how we can write some solr query in c# backend using SolrNet. The first thing you need for this is to add the SolrNet dll reference to your project.

Step 1: Import this two namespace in your controller using SolrNet; using SolrNet.Commands.Parameters;

Step 2: Create new instance of Solr query. Then create a list of array of fields in Solr where the search keyword will be searched. For example on title field, navigation title, description etc. See below code snippet for your reference


 var query = new SolrQuery("*:*");
 if(!string.IsNullOrWhiteSpace(keyword))
 { 
	var q = new[]
	{
		$"(metakeywords_t_{language}:{keyword}",
		$"(title_t_{language}:{keyword}",
		$"(navigationtitle_t_{language}:{keyword}",
		$"(description_t_{language}:{keyword}",
		$"(pagecontent_t_{language}:{keyword}",
	};

	query = new SolrQuery(string.Join(" ", q));
}

Step 3: Add filters to make your search query more efficient. Ex. Add template filter, location filter etc. For this we can use SolrQuery object to write multiple filters. Create a list of Solr queries. There are two properties which is mostly used, SolrQuery and SolrNotQuery

       
var FilterQueries = new List
{
	new SolrQuery("searchable_b:true"),
	new SolrQuery($"_path:{Folder ID}"),
	new SolrQuery(new SolrQuery($"_template:{Template ID}")),
	new SolrNotQuery(new SolrQuery($"_template:{Template ID}")),
}       
	   

If you want to use some facet based filter than use below property SolrFacetFieldQuery


   var Queries = new List { new SolrFacetFieldQuery("Facet Field Name from solr") }

Now let's see how we can use all this feature with small use case. We have requirement to implement Search page which will list down all the pages based on query condition if no search keyword is provided. If keyword is provided then the result will be based on that. Also we like to provide an additional facet filter which will filter the result based on that.

Our task will be adding a new search controller and writing an ajax query to fetch the search results to met the search page requirements.Below is the code snippet for reference. Its self explanatory and can be modified accordinf to its own needs.


[HttpGet]
public ActionResult Search(string search, int skip, int take, string facet)
{
	string language = _context.Language.CultureInfo.Name.Split('-')[0];
	string escapedQuery = ConvertQuery(search);
	string wildcardQuery = ConvertQuery(search, true);
    string ConvertQuery(string searchQuery, bool wildcard = false) => string.Format(
				wildcard ? "(*{0}*)" : "({0})",
				Regex.Replace(
					EscapeTerms(searchQuery),
					@"(? facets = null;
		if (!string.IsNullOrWhiteSpace(facet))
		{
        	// For fetching Facet Count, you need to have full search implementation
			var allResults = context.Query(query, queryOptions);
			facets = allResults.FacetFields?.Values.SelectMany(v => v).ToDictionary(x => x.Key, x => x.Value);
			queryOptions = BuildQueryOptions(skip, take);
			queryOptions.FilterQueries.Add(new SolrQueryByField("docuemnttype_sm", facet));
		}

		queryOptions.Highlight = new HighlightingParameters
		{
			Fields = new List
			{
				$"metadescription_t_{language}",
				$"pagecontent_t_{language}"
			},
			Fragsize = 350,
			BeforeTerm = "",
			AfterTerm = ""
		};

		var results = context.Query(query, queryOptions);
		var resultModels = results.Select(r =>
				new SearchResultModel(r, results.Highlights[r["_uniqueid"]].Snippets, language));

		return Content(JsonConvert.SerializeObject(new
		{
			documents = resultModels.ToList(),
			total = results.NumFound.ToString(),
			facets = facets ?? results.FacetFields?.Values.SelectMany(v => v)
						.ToDictionary(x => x.Key, x => x.Value)
		}), "application/json");

	}
}

private static QueryOptions BuildQueryOptions(int skip, int take)
{
	Sitecore.Data.Items.Item currenthomeitem = Sitecore.Context.Database.GetItem(Sitecore.Context.Site.StartPath);
	var HomeFolderShortId = currenthomeitem.ID.Guid.ToString("N");
	var HomeTemplateShortId = currenthomeitem.TemplateID.Guid.ToString("N");
	return new QueryOptions
	{
		FilterQueries = new List
		{
			new SolrQuery("searchable_b:true"),
			new SolrQuery($"_path:{HomeFolderShortId}"),
			new SolrNotQuery(new SolrQuery($"_template:{HomeTemplateShortId}"))
		},
		StartOrCursor = new StartOrCursor.Start(skip * take),
		Rows = take,
		Facet = new FacetParameters
		{
			Queries = new List { new SolrFacetFieldQuery("docuemnttype_sm") }
		}
	};
}

In above code, we have seen how we can implement both wildcard query as well normal search query. We have seen, how we can implement filter facet, inserting various filter parameter using SolrQuery and SolrNotQuery class. Passing Facet to ISolrFacetQuery class.

SolrNet provides lots of inbuilt classes and objects to write efficient solr query syntax in c# backend. Hope you have learn something here and stay tune for such informative blogs. Thanks for reading and keep learning!!

References: https://github.com/SolrNet/SolrNet/blob/master/Documentation/Querying.md

You can check my other blogs too if interested. Blog Website

Comments

Popular posts from this blog

Sitecore XM Cloud Form Integration with Azure Function as Webhook

Automate RSS Feed to Sitecore XM Cloud: Logic App, Next.js API & Authoring API Integration

Create and Fetch Content From Sitecore Content Hub One using GraphQL and React