1 / 44

Getting started with ElasticSearch on Windows and .NET with NEST

Getting started with ElasticSearch on Windows and .NET with NEST. A short introduction. Oslo/NNUG Meetup. Tomas Jansson. 29/01/2014. This is me. Tomas Jansson Manager & Group Lead .NET BEKK Oslo @TomasJansson tomas.jansson@bekk.no github.com/mastoj blog.tomasjansson.com. TL;DR;.

george
Download Presentation

Getting started with ElasticSearch on Windows and .NET with NEST

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Getting started with ElasticSearch on Windows and .NET with NEST A shortintroduction Oslo/NNUG Meetup Tomas Jansson 29/01/2014

  2. This is me Tomas Jansson Manager & Group Lead .NET BEKK Oslo @TomasJansson tomas.jansson@bekk.no github.com/mastoj blog.tomasjansson.com

  3. TL;DR; https://github.com/mastoj/NestDemo

  4. Audience N00b Expert Expert N00b

  5. BackgrounD This is the data and weneedthisnewapplication

  6. The masterplan

  7. What I want to show you is... • Elasticsearch is awesome • Indexing using NEST • Querying using NEST • ... not about advanced elasticsearch hosting

  8. Installation • Great news, install as a service added in 0.90.5 Powershell to the rescue

  9. NEST Abstraction over Elasticsearch There is an lowlevelabstraction as wellcalledRawElasticClient

  10. NEST Abstraction over Elasticsearch Fluent & Stronglytyped

  11. FunctionalC#

  12. FUNC DEMO • C:\Dev\git> scriptcs • scriptcs (ctrl-c or blank to exit) • > Func<int, int, int> add = (x, y) => x + y; • > add(1, 3) • 4 Func  executable

  13. Simple Expression DEMO • > usingSystem.Linq.Expressions; • > Expression<Func<int, int, int>> addExpr = (x, y) => x + y; • > addExpr(1, 3) • (1,1): error CS1955: Non-invocablemember 'addExpr' cannot be used like a method. • > var binExpr = addExpr.Body as BinaryExpression; • > Console.WriteLine(binExpr); • (x + y) • > var add2 = addExpr.Compile(); • > add2(3, 1); • 4 Expression  ”function description”

  14. More complex Expression DEMO • > public class SomeClass { public string MyString { get; set; } } • > Expression<Func<SomeClass, object>> propExpr = y => y.MyString + y.MyString; • > varcompExpr = propExpr.Compile(); • > varobj = new SomeClass { MyString = "Hello world" }; • > compExpr(obj) • Hello worldHelloworld • > varbody = propExpr.Body as BinaryExpression; • > Console.WriteLine(body); • (y.MyString + y.MyString) • > varleft = body.Left as MemberExpression; • > Console.WriteLine(left.Member.Name); • MyString

  15. More complex Expression DEMO • > public class SomeClass { public string MyString { get; set; } } • > Expression<Func<SomeClass, object>> propExpr = y => y.MyString + y.MyString; • > varcompExpr = propExpr.Compile(); • > varobj = new SomeClass { MyString = "Hello world" }; • > compExpr(obj) • Hello worldHelloworld • > varbody = propExpr.Body as BinaryExpression; • > Console.WriteLine(body); • (y.MyString + y.MyString) • > varleft = body.Left as MemberExpression; • > Console.WriteLine(left.Member.Name); • MyString Enables us to translate from one domain to another in an ”easy” manner

  16. Show me the code!

  17. Elasticsearchconnection • publicclassElasticClientWrapper : ElasticClient • { • privatestaticstring _connectionString=Settings.ElasticSearchServer; • privatestaticConnectionSettings _settings = • newConnectionSettings(newUri(_connectionString)) //http://demoserver:9200 • .SetDefaultIndex(Settings.Alias) //"customer_product_mapping" • .UsePrettyResponses(); • publicElasticClientWrapper() • : base(_settings) • { • } • } • //usage • varclient=newElasticClientWrapper();

  18. Mapping • publicclassProduct • { • publicdoubleUnitPrice { get; set; } • publicintTotalQuantity { get; set; } • [ElasticProperty(Index =FieldIndexOption.not_analyzed)] • publicstringProductName { get; set; } • [ElasticProperty(Index =FieldIndexOption.not_analyzed)] • publicstringCategoryName { get; set; } • } • publicclassCustomer • { • publicstringCustomerID { get; set; } • publicstringCompanyName { get; set; } • publicstring Address { get; set; } • publicstring City { get; set; } • publicstring Country { get; set; } • [ElasticProperty(Type =FieldType.nested)] • publicProduct[] Products { get; set; } • }

  19. Mapping & Indexing • _client=newElasticClientWrapper(); • _client.CreateIndex("indexName", s => • s.AddMapping<Customer>(m =>m.MapFromAttributes())); • varcustomers= _customerRepo.GetCustomers(); • _client.IndexMany(customers, "indexName"); Mapping created from attributes Indexing will use the mapping for the specified index There is async versions of the methods

  20. Alias • _client=newElasticClientWrapper(); • _client.Alias("indexName", "aliasName"); Alias Index_01

  21. Swapping • _client=newElasticClientWrapper(); • _client.Swap("aliasName", new [] { "Index_01" }, new [] { "Index_02" } ); Alias Alias Create new index Swap Delete old index Index_01 Index_02

  22. My query object (Will be used in the examples) • publicclassSearchModel • { • privateint? _numberToTake; • publicstring Query { get; set; } • publicDictionary<string, IEnumerable<string>> Filter { get; set; } • publicint?NumberToTake • { • get{ return _numberToTake.HasValue? _numberToTake.Value : 25; } • set{ _numberToTake=value; } • } • }

  23. QueryinG Elasticsearch NEST • { • "query": { • "query_string": { • "query": "tomas" • } • } • } • _client.Search<Customer>(sd=>sd • .QueryString(Input.Query));

  24. Fuzzy Elasticsearch NEST • { • "query": { • "fuzzy": { • "_all": { • "min_similarity": 0.6, • "prefix_length": 1, • "value": "tomas" • } • } • } • } • _client.Search<Customer>(sd=>sd • .Query(q =>q • .Fuzzy(fd=>fd • .OnField("_all") • .MinSimilarity(0.6) • .PrefixLength(1) • .Value(Input.Query)))); Will enableus to search for both «Thomas» and «Tomas» whenwriting «Tomas»

  25. Fuzzy Improved (using bool query) - Elasticsearch • { • "query": { • "bool": { • "should": [{ • "match": { • "_all": { • "query": "tomas" • } • } • }, • { • "fuzzy": { • "_all": { • "boost": 0.1, • "min_similarity": 0.6, • "prefix_length": 1, • "value": "tomas" • } • } • }] • } • } • }

  26. Fuzzy Improved (using bool query) - NEST • _client.Search<Customer>(sd=>sd • .Query(q =>q • .Bool(b =>b • .Should(newFunc<QueryDescriptor<Customer>, BaseQuery>[] • { • _ => _.Match(m =>m • .OnField("_all") • .QueryString(Input.Query)), • _ => _.Fuzzy(fd=>fd • .OnField("_all") • .MinSimilarity(0.6) • .PrefixLength(1) • .Value(Input.Query) • .Boost(0.1)) • }))));

  27. Highlight result - Elasticsearch • { • "query": { • // seepreviousexample • }, • "highlight": { • "pre_tags": [ • "<span class='highlight'>" • ], • "post_tags": [ • "</span>" • ], • "fields": { • "companyName": { • "fragment_size": 100, • "number_of_fragments": 1 • } • } • } • }

  28. Highlight result - NEST • _client.Search<Customer>(sd=>sd • .Query( /* See previousexample */ ) • .Highlight(h =>h • .PreTags("<span class='highlight'>") • .PostTags("</span>") • .OnFields(newAction<HighlightFieldDescriptor<Customer>>[] • { • _ =>_ • .OnField(c =>c.CompanyName) • .NumberOfFragments(1) • .FragmentSize(100) • })));

  29. Facets - Elasticsearch • { • "query": { /* See previousexample */ }, • "highlight": { /* See previousexample */ }, • "facets": { • "products.productName": { • "nested": "products", • "terms": { "field": "products.productName", "size": 1000 } • }, • "products.categoryName": { • "nested": "products", • "terms": { "field": "products.categoryName", "size": 1000 } • }, • "country": { • "terms": { "field": "country", "size": 1000 } • } • } • }

  30. Facets - NEST • _client.Search<Customer>(sd=>sd • .Query( /* See previousexample */) • .Highlight( /* See previousexample */) • .FacetTerm(f =>f • .Nested(c =>c.Products) • .OnField(c =>c.Products[0].ProductName) • .Size(1000)) • .FacetTerm(f =>f • .Nested(c =>c.Products) • .OnField(c =>c.Products[0].CategoryName) • .Size(1000)) • .FacetTerm(f =>f • .OnField(c =>c.Country) • .Size(1000)));

  31. http://go-gaga-over-testing.blogspot.no/2011/09/solution-to-warning-in-quality-center.htmlhttp://go-gaga-over-testing.blogspot.no/2011/09/solution-to-warning-in-quality-center.html

  32. Filters - Elasticsearch • { • "query": { • "filtered": { • "query": { /* See previousexample */ }, • "filter": { • "bool": { • "must": [ • { • "terms": { "country": ["usa"] } • }, • { • "nested": { • "query": { "terms": { "products.categoryName": ["Condiments", "Seafood"] } }, • "path": "products" • } • }, • { • "nested": { • "query": { "terms": { "products.productName": ["Chai"] } }, • "path": "products" • } • } • ] • } • } • } • }, • "facets": { /* See previousexample */}, • "highlight": { /* See previousexample */ } • }

  33. Filters – NEST – Part 1, the Customers filter • privatestaticBaseFilterAddCustomerFilter(IEnumerable<string>items, Expression<Func<Customer, object>>propExpr) • { • returnFilter<Customer>.Terms(propExpr, items.ToArray()); • }

  34. Filters – NEST – Part 1, the Products filter • privatestaticBaseFilterAddProductsFilter(IEnumerable<string> items, • Expression<Func<Customer, object>>propExpr) • { • returnFilter<Customer>.Nested(sel => sel • .Path(c =>c.Products) • .Query(q =>q.Terms(propExpr, items.ToArray()))); • }

  35. Filters – NEST – Part 1, the Magic Dictionary • publicDictionary<string, Func<IEnumerable<string>, BaseFilter>>FilterDesc= • newDictionary<string, Func<IEnumerable<string>, BaseFilter>>() • { • {"products.productName", ps=>AddProductsFilter(ps, c => c • .Products[0].ProductName)}, • {"products.categoryName", cs=>AddProductsFilter(cs, c =>c • .Products[0].CategoryName)}, • {"country", cs=>AddCustomerFilter(cs, c =>c.Country)} • };

  36. Filters – NEST – Part 1, All the helpers • privatestaticBaseFilterAddCustomerFilter(IEnumerable<string>items, Expression<Func<Customer, object>>propExpr) • { • returnFilter<Customer>.Terms(propExpr, items.ToArray()); • } • privatestaticBaseFilterAddProductsFilter(IEnumerable<string> items, • Expression<Func<Customer, object>>propExpr) • { • returnFilter<Customer>.Nested(sel => sel • .Path(c =>c.Products) • .Query(q =>q.Terms(propExpr, items.ToArray()))); • } • publicDictionary<string, Func<IEnumerable<string>, BaseFilter>>FilterDesc= • newDictionary<string, Func<IEnumerable<string>, BaseFilter>>() • { • {"products.productName", ps=>AddProductsFilter(ps, c => c • .Products[0].ProductName)}, • {"products.categoryName", cs=>AddProductsFilter(cs, c =>c • .Products[0].CategoryName)}, • {"country", cs=>AddCustomerFilter(cs, c =>c.Country)} • };

  37. Filters – NEST – Part 2, The query • _client.Search<Customer>(sd=>sd • .Query(q =>q • .Filtered(fq=> • { • fq.Query(qs=> • { • if(!string.IsNullOrEmpty(Input.Query)) • { • qs.Bool( /* See previousexample */)); • } • else • { • qs.MatchAll(); • } • returnqs; • }); • if(Input.Filter.Count>0) • { • varfilters = • Input.Filter.Select(_ =>FilterDesc[_.Key](_.Value)).ToArray(); • fq.Filter(fs=>fs.Bool(bf =>bf.Must(filters))); • } • })) • .Highlight( /* See previousexample */) • .FacetTerm( /* See previousexample */) • .FacetTerm( /* See previousexample */) • .FacetTerm( /* See previousexample */);

  38. Summary Elasticsearch NEST • Easy installation • Awesome search engine • Strongly typed client • Fluent • Abstraction over Elasticsearch

  39. ResourceS • Demo code: https://github.com/mastoj/NestDemo • Nest documentation: http://nest.azurewebsites.net/ • Nest source code: https://github.com/Mpdreamz/NEST • Slideshare: http://www.slideshare.net/mastoj/getting-started-with-elasticsearch-and-net • Sense (greattool to queryelasticsearch in thebrowser): https://github.com/bleskes/sense

  40. Questions?

  41. Thank you! @TomasJansson

More Related