• Thu. Nov 21st, 2024

Tony's Bit

Software Development, Cloud Computing, Blockchain Technology and Finance.

C# Time-savers for Elasticsearch

ByTony Nguyen

Jun 23, 2018

1. Context

If you are currently developing using C# (Particularly .NET Core 2.0+) here are some shortcuts I hope will be able to save you time I wish I could have back.

There is official documentation for C# Elasticsearch development however I found the examples to be quite lacking. I do recommend going through the documentation anyway especially for the NEST client as it is essential to understand Elasticsearch with C#.

1. Low Level Client

“The low level client, ElasticLowLevelClient, is a low level, dependency free client that has no opinions about how you build and represent your requests and responses.”

ElasticSearch Official Documentation

Unfortunately the low level client in particular has very sparse documentation especially examples. The following was discovered through googling and painstaking testing.

1.1. Using  JObjects in Elasticsearch

JObjects are quite popular way to work with JSON objects in .NET, as such it may be required to parse JObjects to Elasticsearch, this may be a result of one of the following:

  • Definition of the object is inherited from a different system and only parsed to Elasticsearch via your application (i.e. micro-service)
  • Too lazy to strongly define each object as it is unnecessary

The JObject cannot be used as the generic for indexing as you will receive this error:

70cb251f-fb84-4495-a518-bb028d60ced9
Figure 1: ‘JObject’ Cannot be used as type parameter

Instead use “BytesResponse” as the <T> Class

c0b5c968-1772-4639-a1ce-5bd286fb1365
Figure 2: Using BytesResponse

1.2. Running a “Bool” query

The examples given by the Elasticsearch documentation does not give an example of a bool query using the low-level client. Why is the “Bool” query particularly difficult? Using Query DSL in C#, “bool” will automatically resolve to the class and therefore will throw a error:

57735edf-10ac-4bcf-b652-44803f6d6653
Figure 3: bool Error

Not very anonymous type friendly… the solution to this one is quite simple, add a ‘@’ character in-front of the bool.

93a84b9e-c9bd-4b39-8207-2046a516773a
Figure 4: Anonymous bool Fix

1.3. Defining Anonymous Arrays

This one seems a-bit obvious but if you want to define an array for use with DSL, use the anonymous typed Array (Example can be seen in figure 4) new Object[].

1.4. Accessing nested fields in searches

Nested fields in Elasticsearch are stored as a full path, . delimited string. This creates a problem when trying to query that field specifically as it creates a invalid type for anonymous types.

fc91bf91-d27d-4358-8621-151abc285d77
Figure 5: Nested Field Error

The solution is to define a Dictionary and use the dictionary in the anonymous type.

80642ca4-05ef-4739-bc80-24af5b895527.png
Figure 6: Nested Field Fix

The Dictionary can be passed by the anonymous type and will successfully query the Nested field in Elasticsearch.

2. NEST Client

“The high level client, ElasticClient, provides a strongly typed query DSL that maps one-to-one with the Elasticsearch query DSL.”

ElasticSearch Official Documentation

The NEST documentation is much more comprehensive, the only issue I found was using keyword Term searches.

2.1. Using Keyword Fields

All string fields are mapped by default to both text and keyword, the documentation can be found here. Issue is that in the strong typed object used in the Elastic Mapping there is no “.keyword” field to reference therefore a error is thrown.

Example:

For the Object:

public class SampleObject
{
public string TextField { get; set; }
}

Searching would look like this

d02803f8-113d-42bd-b1ce-eac3850d1bcd
Figure 7: Keyword Field Error

Unfortunately the .Keyword field does not exist, the solution is using the .Suffix function using property name inference. This is documented in the docs however it is not immediately apparent that is how you access “keyword”.

f1da2aca-85a0-43b8-81bf-1be26ebb5ebf
Figure 8: Keyword Fix

I hope this post was helpful and saved you some time. If you have any tips of your own please comment below!