Returning multiple derived class instances from Elasticsearch using NEST and .NET

zorlack

I'm trying to use NEST to return various objects derived from a common subclass.

In this example I have a base class called "Person" and then I have derived classes called "Firefighter" and "Teacher". Instances are stored in an index called "people".

I'd like to do a search on my index and return a mix of Firefighters and Teachers, but the best I can get back is a list of Persons.

The documentation calls for the use of ISearchResponse.Types, but I don't see that this function exists. This post, here on StackOverflow, also references the .Types function but I just don't see it as an option.

Here's an example of the problem I'm trying to solve.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nest;
using Elasticsearch;
using Elasticsearch.Net;

namespace ElasticSearchTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var myTeacher = new Teacher { id="1", firstName = "Steve", lastName = "TheTeacher", gradeNumber = 8 };
            var myFiregighter = new Firefighter { id="2", firstName = "Frank", lastName = "TheFirefighter", helmetSize = 12 };

            SingleNodeConnectionPool esPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
            ConnectionSettings esSettings = new ConnectionSettings(esPool);
            esSettings.DefaultIndex("people");
            Nest.ElasticClient esClient = new ElasticClient(esSettings);

            esClient.DeleteIndex("people");
            esClient.Index<Teacher>(myTeacher);
            esClient.Index<Firefighter>(myFiregighter);

            System.Threading.Thread.Sleep(2000);

            ISearchResponse<Person> response = esClient.Search<Person>(s => s   
                .AllTypes()
                .MatchAll()
                );

            foreach (Person person in response.Documents)
                Console.WriteLine(person);
        }

        public class Person
        {
            public string id { get; set; }
            public string firstName { get; set; }
            public string lastName { get; set; }
            public override string ToString() { return String.Format("{0}, {1}", lastName, firstName);}
        }
        public class Firefighter : Person
        {
            public int helmetSize { get; set; }
        }
        public class Teacher : Person {
            public int gradeNumber { get; set; } 
        }
    }
}

The data appears to be structured correctly inside Elasticsearch:

{
    took: 1,
    timed_out: false,
    _shards: {
        total: 5,
        successful: 5,
        failed: 0
    },
    hits: {
        total: 2,
        max_score: 1,
        hits: [{
            _index: "people",
            _type: "firefighter",
            _id: "2",
            _score: 1,
            _source: {
                helmetSize: 12,
                id: "2",
                firstName: "Frank",
                lastName: "TheFirefighter"
            }
        }, {
            _index: "people",
            _type: "teacher",
            _id: "1",
            _score: 1,
            _source: {
                gradeNumber: 8,
                id: "1",
                firstName: "Steve",
                lastName: "TheTeacher"
            }
        }]
    }
}

How do I get NEST to return a mixed list of instances derived from a base class?

Many thanks!

-Z

Russ Cam

NEST supports Covariant results and in NEST 2.x, the naming of the method on ISearchResponse<T> was changed to .Type() to align with the route parameter that it represents in the URI when making the request to Elasticsearch (.Type() can be one or more types).

An example of Covariant results for NEST 2.x is

static void Main(string[] args)
{
    var myTeacher = new Teacher { id = "1", firstName = "Steve", lastName = "TheTeacher", gradeNumber = 8 };
    var myFiregighter = new Firefighter { id = "2", firstName = "Frank", lastName = "TheFirefighter", helmetSize = 12 };

    SingleNodeConnectionPool esPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    ConnectionSettings esSettings = new ConnectionSettings(esPool);
    esSettings.DefaultIndex("people");
    Nest.ElasticClient esClient = new ElasticClient(esSettings);

    if (esClient.IndexExists("people").Exists)
    {
        esClient.DeleteIndex("people");
    }

    esClient.Index<Teacher>(myTeacher, i => i.Refresh());
    esClient.Index<Firefighter>(myFiregighter, i => i.Refresh());

    // perform the search using the base type i.e. Person
    ISearchResponse<Person> response = esClient.Search<Person>(s => s
        // Use .Type to specify the derived types that we expect to return
        .Type(Types.Type(typeof(Teacher), typeof(Firefighter)))
        .MatchAll()
    );

    foreach (Person person in response.Documents)
        Console.WriteLine(person);
}

public class Person
{
    public string id { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public override string ToString() { return String.Format("{0}, {1}", lastName, firstName); }
}
public class Firefighter : Person
{
    public int helmetSize { get; set; }
}
public class Teacher : Person
{
    public int gradeNumber { get; set; }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to get in ElasticSearch derived class NEST

Returning a derived type from factory class

SingleTon class is not synchronized and returning multiple instances

NEST elasticsearch.NET search query not returning results (part 2)

Elasticsearch.NET & NEST - search always returning 0 results

Multiple values in QueryString query using elasticsearch NEST

Search by multiple values using NEST(ElasticSearch)

Searching in multiple elasticsearch indexes using NEST

returning derived class from overrided method, declared as returning base copy

Calling derived class instances from a stack of a base class

How to use two instances of a base class from a derived class

Returning a reference to the derived class from a base class method

Using JSON.NET to deserialize to a derived class

.NET NEST client for Elasticsearch

ElasticSearch with Nest: Partial search using multiple words using Query<>.Wildcard

.NET ElasticSearch NEST - NGram Analyzer on Multiple Fields for Partial Matches

Returning any derived class type from a method outside the base and derived class

How to search inside multiple indices using Nest ElasticSearch?

Elasticsearch using NEST - No Results

How to write constructors for implicit conversions from instances of a templated class C<Derived> to instances of C<Base>

Execute raw JSON request using NEST / Elasticsearch.Net

How to compare attributes from multiple class instances?

Instantiating multiple instances of a class from within

Creating a multiple class instances from user input

× ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

Running multiple elasticsearch instances

Using decorator from base class both in base class and derived class

C++ Multiple inheritance casting from derived class to base class

.Net Core DI injection Abstract class using Interface in a derived class