Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to search for GUIDs in Nest.Net in elasticsearch?

I am using Nest which is a .Net client for elasticsearch. I have a problem when searching for GUIDs. As the GUID has "-", elasticsearch is considering as tokens.

Below is the problem I am facing.

I have an entity "Employee" with following properties.

   Id : Guid 
   Name : varchar 
   DepartmentId : Guid (E.g cb5d39ee-05f0-4351-baba-8eed6c9111ad)

Now I need to get the list of employees who are belongs to particular department. So I will pass the department Id.

As there is a "-" in DepartmentId, elasticsearch is considering as a separator due to which I couldn't get the results.

Employee class

public class Employee
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    [ElasticProperty(Analyzer = "keyword")]
    public Guid DepartmentId { get; set; }
}

Below is the sample code.

 class Program
{
    static string indexName = "Elasticsearchsamples".ToLowerInvariant();        

    private static void IndexEmployees()
    {
        List<Employee> employees = new List<Employee>();
        Employee employee;

        var deptId = new Guid("cb5d39ee-05f0-4351-baba-8eed6c9111ad");

        employee = new Employee()
        {
            Id = Guid.NewGuid(),
            Name = "Raja",
            DepartmentId = deptId
        };
        employees.Add(employee);

        employee = new Employee()
        {
            Id = Guid.NewGuid(),
            Name = "Ram",
            DepartmentId = deptId
        };
        employees.Add(employee);

        employee = new Employee()
        {
            Id = Guid.NewGuid(),
            Name = "Guru",
            DepartmentId = Guid.NewGuid()
        };
        employees.Add(employee);

        if (SearchClient.IsConnected())
        {
            SearchClient.ElasticClientInstance.DeleteIndex(indexName);              

            var result = SearchClient.ElasticClientInstance.IndexMany(employees, indexName);
        }
    }

    private static void SearchEmployees()
    {

        var searchDescriptor = new SearchDescriptor<Employee>();
        searchDescriptor.Index(indexName);
        var deptId = new Guid("cb5d39ee-05f0-4351-baba-8eed6c9111ad");
        searchDescriptor.Query(qq => qq.Term(x => x.DepartmentId, deptId.ToString().ToLowerInvariant()));
        //searchDescriptor.Query(qq => qq.Term(x => x.Name, "raja"));

        var result = SearchClient.ElasticClientInstance.Search(searchDescriptor);
        Console.WriteLine(result.Total);
    }

    static void Main(string[] args)
    {
        System.Net.ServicePointManager.Expect100Continue = false;            
        IndexEmployees();
        SearchEmployees();
        Console.Read();
    }
}
like image 515
Thangaraja Avatar asked Dec 15 '22 22:12

Thangaraja


1 Answers

On your Employee class you need to tell Elasticsearch to either not analyze the DepartmentId field or use the keyword analyzer. Please note that the documentation for the keyword analyzer suggests the following:

An analyzer of type keyword that "tokenizes" an entire stream as a single token. This is useful for data like zip codes, ids and so on. Note, when using mapping definitions, it might make more sense to simply mark the field as not_analyzed.

You can do either of these like the following:

 //do not analyze the value
 [ElasticProperty(Index = FieldIndexOption.not_analyzed)]
 public Guid DepartmentId;

 //use keyword analyzer
 [ElasticProperty(Analyzer = "keyword")]
 public Guid DepartmentId;
like image 67
Paige Cook Avatar answered Dec 31 '22 16:12

Paige Cook