📜 ⬆️ ⬇️

LinqToSolr - use LINQ to get data from Solr

image
Due to the fact that in our company as a full-text search platform, the choice fell on Solr, there was a strong desire to simplify work with queries to Solr through the use of LINQ expressions.

Having reviewed the Internet for the availability of alternatives, I came to the conclusion that at the moment I do not need the library in general access. The maximum that was found was a very partial implementation of queries in Solr.NET (and the author’s skeptical commentary ).

The result was a small library LinqToSolr ( GitHub project ), which contains the implementation of the IQueriable interface <> with the ability to convert requests into a clear Solr API and back.

Implemented Enumerable Methods


Currently, implementations of the following methods are available:
')

Configuration


So, first you need to configure the connection and adjust the ratio of our data model to Solr indices.

Let's start with the configuration, but first define the presentation of the Solr document as a normal class:

public class MyProduct{ [JsonProperty("ProductId")] public int Id{get;set;} public string Name{get;set} public string Group{get;set} public double Price {get;set;} public bool IsDeleted{get;set} } 

Above is a class that describes the Solr index, which has Id, Name, Group, Price, and IsDeleted typed fields. With a strong desire, you can use the JsonProperty property, to override the field names (for example, the Id field).

Create a configuration:

 var config = new LinqToSolrRequestConfiguration("http://localhost:1433/") .MapIndexFor<MyProduct>("MyProductIndex"); 

What do we see here? First, we provide an address to Solr.

Next, we indicate the projection of our classes to the Solar indices. It is natural to assume that we can specify as many classes as necessary to different indices. The only condition is that one class must correspond to a single index. The minimum configuration is ready.

Initialize the service itself:

 var service = new LinqToSolrService(config); 

Everything. We have fulfilled all the conditions to start using Linq to Solr.

Examples of using


FirstOrDefault method


 service.AsQueriable<MyProduct>().FirstOrDefalult(x=> x.Id == 1); 

Where method


Select all documents in the group:

 service.AsQueriable<MyProduct>().Where(x=>x.Group == "Group1").ToList(); 

An example of the implementation of using functions within linq queries:

 service.AsQueriable<MyProduct>().Where(x=>x.Group.Contains("roup")).ToList(); service.AsQueriable<MyProduct>().Where(x=>x.Group.StartsWith("Gro")).ToList(); service.AsQueriable<MyProduct>().Where(x=>x.Group.EndsWith("up1")).ToList(); 

An example of a search in an array:

 var groupsArr= new[] { "Group1", "Group2", "Group3" }; service.AsQueriable<MyProduct>().Where(x=> groupsArr.Contains(x.Group)).ToList(); 

An example of a sample with "more-less":

 service.AsQueriable<MyProduct>().Where(x=> x.Price >= 500 && x.Price < 1000).ToList(); 

We use several Where:

 service.AsQueriable<MyProduct>() .Where(x=> !x.IsDeleted) .Where(x=>x.Name.Contains("somepartofthename")) .ToList(); 

Sort documents


 service.AsQueriable<MyProduct>() .Where(x=> !x.IsDeleted) .OrderByDescending(x=> x.Group) // DESC .ThenBy(x=>x.Name) // ASC .ToList(); 

Choose a certain number


 service.AsQueriable<MyProduct>().Where(x=> !x.IsDeleted).Take(100).Skip(400).ToList(); 

Select method


 //   service.AsQueriable<MyProduct>().Where(x=> !x.IsDeleted).Select(x=> x.Name).ToList(); //    dynamic- service.AsQueriable<MyProduct>().Where(x=> !x.IsDeleted).Select(x=> new {x.Name, x.Group}).ToList(); 

Work with Facets


 service.AsQueriable<MyProduct>().Where(x=> !x.IsDeleted).GroupByFacets(x=>x.Name, x=>x.Group).ToList(); 

In the example above, we request Solr to give us back 2 groups - Name and Group.

You can also use the GroupBy method. He, in turn, will return a similar option, but also add grouped documents. What is better to use - you choose. Facets are faster, but you need to make 2 server requests to get a list of documents. GroupBy - works more slowly, since it returns, besides the groups, the documents themselves are already sorted into groups.

Debugging and checking


In any case, there is a need to verify the request and response. This can be done using the LastResponse object built into the service. In fact, this is the Solr server response view. Plus, the URL of the query (LastRequestUrl) is located there, which can be used in the browser to check what Solr actually returns.

Service


Naturally, using LinqToSolrService directly is not very convenient. We create our own service inherited from LinqToSolrService.

 public class MySolrService : LinqToSolrService { public MySolrService(LinqToSolrRequestConfiguration config) : base (config) { } public IQueryable<MyProduct> NotDeleted() { return AsQueryable<MyProduct>().Where(x=> !x.IsDeleted); } public ICollection<MyProduct> GetProducts(params int[] ids) { return NotDeleted().Where(x=> ids.Contains(x.Id)).OrderBy(x=>x.Name).ToList(); } public MyProduct GetProduct(id) { return NotDeleted().FirstOrDefault(x=> x.Id == id); } public string[] GetGroups(id) { return NotDeleted().GroupBy(x=> x.Group).ToArray(); } } 

Total


I hope someone who uses Solr in .NET projects will also benefit from a library.
Currently the most obvious requests are implemented.

Plans to add support for Boost, Proximity and query functions.

Source: https://habr.com/ru/post/327002/


All Articles