3

I have a multiSearch query as below. Basically I query product and category types. I would like to make this query optional without writing same code again. Basically in some cases I want to query only product type, that means that it will not multisearch but a search query. How can I split this query into 2 search queries. Something like below I think.

    return Client.MultiSearch(ms => ms
        .Search<Product>("products", s => s
        .Index(IndexName)
        .Explain(explain)
          .Query(q => q
             .Bool(b => b
                 .Should(
                     sh => sh.MultiMatch(qs => qs
                         .Fields(d => d                         
                             .Field(Name + ".raw", NameBoost + 0.5)
                             .Field(Name, NameBoost)                            
                            .Type(TextQueryType.BestFields)
                            .Query(key))
                            ))).From(startfrom).Size(size))
.Search<Category>("categories", s => s
.Index(IndexName)
.Explain(explain)
.Query(q => q.
Bool(b => b.
Should(sh => sh.
MultiMatch(m => m
.Fields(d => d
.Field(f => f.Name, NameBoost)
.Field(p => p.Name.Suffix("raw"), NameBoost + 0.5)).Type(TextQueryType.BestFields)
.Query(key)
)
))).From(startfrom).Size(size))
);

something like this below. I guess that it is called object initializer Syntax according to this article

Client.MultiSearch (SearchProductQuery && SearchCategoryQuery)

is it possible?

2
  • What version of NEST are you using? Also, what version of Elasticsearch are you targeting? Commented May 9, 2016 at 3:05
  • @RussCam I am using for both 2.1.0 version Commented May 9, 2016 at 8:53

1 Answer 1

5

This fluent API multi search

client.MultiSearch(ms => ms
    .Search<Product>("products", s => s
        .Index(IndexName)
        .Explain(explain)
        .Query(q => q
           .Bool(b => b
                .Should(sh => sh
                    .MultiMatch(qs => qs
                        .Fields(d => d
                            .Field(Name + ".raw", NameBoost + 0.5)
                            .Field(Name, NameBoost)
                        )
                        .Type(TextQueryType.BestFields)
                        .Query(key)
                    )
                )
            )
        )
        .From(startfrom)
        .Size(size)
    )
    .Search<Category>("categories", s => s
        .Index(IndexName)
        .Explain(explain)
        .Query(q => q
            .Bool(b => b
                .Should(sh => sh
                    .MultiMatch(m => m
                        .Fields(d => d
                            .Field(f => f.Name, NameBoost)
                            .Field(p => p.Name.Suffix("raw"), NameBoost + 0.5)
                        )
                        .Type(TextQueryType.BestFields)
                        .Query(key)
                    )
                )
            )
        )
        .From(startfrom)
        .Size(size)
    )
);

would be this OIS API multi search

var multiSearch = new MultiSearchRequest
{
    Operations = new Dictionary<string, ISearchRequest>
    {
        { "products", new SearchRequest<Product>(IndexName)
            {
                Explain = true,
                Query = new BoolQuery
                {
                    Should = new QueryContainer[] {
                        new MultiMatchQuery
                        {
                            Fields = 
                                ((Fields)Field.Create(Name + ".raw", NameBoost + 0.5))
                                .And(Name, NameBoost),
                            Type = TextQueryType.BestFields,
                            Query = key
                        }
                    }
                },
                From = startfrom,
                Size = size
            }
        },
        { "categories", new SearchRequest<Category>(IndexName)
            {
                Explain = true,
                Query = new BoolQuery
                {
                    Should = new QueryContainer[] {
                        new MultiMatchQuery
                        {
                            Fields =    
                                ((Fields)Infer.Field<Category>(f => f.Name, NameBoost))
                                .And<Category>(f => f.Name.Suffix("raw"), NameBoost + 0.5),
                            Type = TextQueryType.BestFields,
                            Query = key
                        }
                    }
                },
                From = startfrom,
                Size = size
            }
        },
    }
};

client.MultiSearch(multiSearch);

Take a look at the multi search integration tests for another example. I'll look at getting this added to the documentation.

Sign up to request clarification or add additional context in comments.

4 Comments

is there any performance difference between them? I see that for product you used Field.Create for category Infer.Field<Category>? what is the difference? you added as alternative or any purpose?
I just showed them as alternative ways of getting a field. Strings are faster than expressions but you get no type safety nor ease of refactoring (nameof(Type.Property) can help here)
regarding performance. I wanted to compare my original with the field inference. Is my original one actually also a field inference? I went through this link and It tells me that with C# 6, I can use just like my original one. elastic.co/guide/en/elasticsearch/client/net-api/2.x/…
strings are accepted verbatim i.e. they undergo no inference so if you use strings, you need to ensure that they match the field names in the mapping e.g. case has to be correct. Expressions are inferred so e.g. with the default inference, f => f.Name will be inferred as "name"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.