Write genric search query using nest C# client

Hi i am trying to use nest client for c# to write search query .
i know these ways of writing query

            var searchresponse = client.Search<test>(s => s
                                        .From(0)
                                        .Size(10)
                                        .Index("sales*")
                                        .Query(q => q
                                             .Match(m => m
                                                .Field(f => f.documenttype)
                                                .Query("salesinvoice")
                                             )
                                        )
                                    );

other way of doing same thing

            var searchResponse = client.LowLevel.Search<StringResponse>("sales*", @"
            {
                ""from"": 0,
                ""size"": 10,
                ""query"": {
                    ""match"": {
                        ""documenttype"": {
                            ""query"": ""SalesInvoice""
               }
                    }
                }
            }");

But i want to create some generic function where my class type can be pass as argument

 var searchresponse = client.Search<T>((s => s
                                             .From(0)
                                             .Size(10)
                                             .Index("sales*")
                                             .Query(q => q
                                                  .Match(m => m
                                                     .Field(f => f.documenttype)
                                                     .Query("salesinvoice")
                                                  )
                                             )

is there any way where i can do some thing like this , where my class type can be generic for ES client .
As response i directly want to map with my class type .
any help or suggestion .
Thanks .

You can write a generic method over Search<T>(). Member expressions such as .Field(f => f.documenttype) would require T to be contrained to a generic parameter that has a property getter for a property named documenttype. This can be achieved by putting a generic parameter constraint on the generic method such that T must implement a specific interface e.g.

public static ISearchResponse<T> MySearch<T>(IElasticClient client) 
    where T: class, IMyDocument =>
	client.Search<T>(s => s
		.From(0)
		.Size(10)
		.Index("sales*")
		.Query(q => q
			 .Match(m => m
				.Field(f => f.documenttype)
				.Query("salesinvoice")
			 )
		)
	);

public interface IMyDocument
{
	string documenttype { get; } 
}

Thanks for reply ,
but still i need to create mysearch function again if my interface changes
for example one as u given example of IMyDocument .
i have another index says inventory .
where i don't have documenttype i may have field called outofstock .
so i need to create another search function where it will be -
where T: class, IStock =>
correct me if i m wrong.
regards
Dilip

The question being asked is really a C# design question and not specific to the client.

If a generic method over some T performs strongly typed access to members of T as in the case of field

then those members need to exist on T. The parts of the search request that perform access to members of T could be pulled out of the generic method and passed to it. As an example

public class Document
{
    public int Id { get; set; }
	public int LocalityId { get; set; }
    public IGeoShape LocationShape { get; set; }
}

public static class ElasticClientExtensions
{
	public static ISearchResponse<T> SearchWithMatch<T>(this IElasticClient client, Expression<Func<T, object>> field)
		where T : class =>
		client.Search<T>(s => s
			.From(0)
			.Size(10)
			.Index("sales*")
			.Query(q => q
				.Match(m => m
					.Field(field)
					.Query("salesinvoice")
				)
			)
		);
}

static void Main()
{
	var client = new ElasticClient();
	var response = client.SearchWithMatch<Document>(f => f.LocalityId);
}

the field for the match query is provided to the generic SearchWithMatch<T>() extension method.

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.