Skip to content

khalidabuhakmeh/NElasticsearch

 
 

Repository files navigation

NElasticsearch

An alternative Elasticsearch client for .NET, built on-the-go while working on real-world projects

Installation

PM> Install-Package NElasticsearch

See https://www.nuget.org/packages/NElasticsearch

Why?

Yeah, there is an officially released (or, to be released) Elasticsearch client for .NET, and also several others out there, but I found them all not satisfactory for my requirements.

This is a client library which is a result of multiple spikes I made while working on real-world project using Elasticsearch. I believe a consumer library written while dogfooding can shape up to be much better to the developer using it.

You can think of this as an experiment in consumer library deisn. I may either succeed in producing a highly-usable, high-performance client library for the popular Elasticsearch fame, or I may learn a lesson or two along the way. Either way, fun.

And the main goals behind this implementation are more or less the following:

Because of easier query syntax

This:

var filter = new {missing = new {field = "redirect"}};
var match_phrase = new {query = q, analyzer = "hebrew_query"};

var query = new
{
filtered = new
          {
              query = new
                      {
                          @bool = new
                                  {
                                      should = new object[]
                                               {
                                                   new {match_phrase = new{title = match_phrase}},
                                                   new {match_phrase = new{text = match_phrase}},
                                               },
                                      minimum_should_match = 1,
                                  }
                      },
              filter = filter,
          }
};

var results = client.Search<ContentPage>(new
          {
              query = query,

              highlight = new
                          {
                              fields = new
                                       {
                                           title = new {number_of_fragments = 0 },
                                           text = new {},
                                       },
                              pre_tags = new[] {"<b>"}, post_tags = new[]{"</b>"},
                              
                          },

              fields = new[] { "title", "categories", "author" },

              aggregations = new {categories = new
                                  {
                                      terms = new
                                              {
                                                  field = "categories",
                                                  size = 50,
                                                  //filter = filter,
                                              }
                                  }},

              from = pageSize * (page - 1),
              size = pageSize,
          });

Is much better than this:

var results = await elasticClient.SearchAsync<ContentPage>(
   search => search.Type("contentpage").Index("hebrew-wikipedia-20140208").Query(
       mainQuery => mainQuery.Filtered(filtered => filtered.Query(
        query => query.Bool(b => b.Should(
            bc => bc.MatchPhrase(_ => _.OnField("title").QueryString(q)),
            bc => bc.MatchPhrase(_ => _.OnField("text").QueryString(q))
            ) // .Analyzer("hebrew_query")
          )
         ).Filter(
            filter => filter.And(_ => _.Missing("redirect"))
         )
       ))
       .Highlight(h => h.PreTags("<b>").PostTags("</b>").OnFields(_ => _.OnField("title").NumberOfFragments(0), _ => _.OnField("text")))
       .Fields("title", "categories", "author")
       .FacetTerm("categories", f => f.OnField("categories").FacetFilter(filter => filter.And(_ => _.Missing("redirect"))).Size(50))
       .Size(pageSize).Skip(pageSize * (page - 1))
   );

In so many ways.

And we can now also do much better since we can easily introduce extension methods and helpers (upcoming).

Because query syntax should match closer to the docs

Continuing on the previous point, either you are cloning the JSONs to be used from C#, or you use easy C# syntax that generates it. No real sense in mimicing JSON structure with method calls.

By providing JSON-like syntax in code (anonymous objects) you can now copy-paste from the excellent Elasticsearch docs and not scratch your head too much trying to map JSONs to nested method calls.

Anonymous objects can also be easily reused (like shown above), because they are just objects.

Because dog-fooding

There's no better way of creating a consumer product than being the consumer yourself.

Because dependency on JSON.NET is a disaster waiting to happen

Unfortunately the current state of affairs with strong named libraries makes it very probably that in one point or another you will find yourself fighting to make your project run again due to version conflicts

Because we can leverage RestSharp

RestSharp is an awesome library that can take care of all the REST chatter over HTTP for us reliably, no need to reinvent the wheel.

Because extension points

Well, that isn't implemented yet, but you'll see.

More to come...

About

An alternative Elasticsearch client for .NET, built on-the-go while working on real-world projects

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%