Necoras
Necoras

Reputation: 7552

How do I construct an ElasticSearch search using NEST with fields from multiple types without magic strings

I'm setting up a system where my search indexed objects are Entities which map back to a normalized SQL database. So on the SQL side I may have a Company which is linked to one or more Company_Address records, as well as Company_Email records, etc. But all of the relevant searchable fields will be in a single Company indexed document tying back to the Company's unique id field.

I'm trying to setup queries which will return the relevant id based on comparing a user provided query string with specific fields in the indexed document. I can do so with a query similar to:

var searchResponse = this.client.Search<Company>(search => search.Query(
    s => s.MultiMatch(
        m => m.Query(query.QueryString)
            .Fields(f => f.Field(c => c.Name).Field("Address1")) // Magic strings go here
            .Fuzziness(Fuzziness.Auto)
        )).Index<Company>());

I'd like to be able to replace "Address1" with ca.Address1 where ca is a CompanyAddress object. Is there a way to construct a collection of FieldDescriptor objects with multiple backing types and then supply that to the search query?

Upvotes: 1

Views: 798

Answers (1)

Russ Cam
Russ Cam

Reputation: 125488

You can construct a Fields instance in a number of ways:

  1. Building a Fields instance by chaining Field instances, constructing those from member access Lambda expressions on some type T

        var searchResponse = this.client.Search<Company>(search => search
            .Query(q => q
                .MultiMatch(m => m
                    .Query("query")
                    .Fields(
                        Infer.Field<Company>(c => c.Name)
                        .And<CompanyAddress>(c => c.Address1)
                    )
                    .Fuzziness(Fuzziness.Auto)
                )
            )
            .Index<Company>()
        );
    
  2. Using nameof with the Address1 property of CompanyAddress

    var searchResponse = this.client.Search<Company>(search => search
        .Query(q => q
            .MultiMatch(m => m
                .Query(query.QueryString)
                .Fields(f => f
                    .Field(c => c.Name)
                    .Field(nameof(CompanyAddress.Address1))
                )
                .Fuzziness(Fuzziness.Auto)
            )
        )
        .Index<Company>()
    );
    

Upvotes: 2

Related Questions