Elasticsearch.Net and multisearch


(Karoline Brynildsen) #1

How do you perform a multisearch with Elasticsearch.Net? I cannot find any examples of this.


(Russ Cam) #2

Here's an example using the fluent lambda API

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)
    )
);

And the same with the Object Initializer syntax

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 integration tests for another example: https://github.com/elastic/elasticsearch-net/blob/5.x/src/Tests/Search/MultiSearch/MultiSearchApiTests.cs#L52-L81


(Karoline Brynildsen) #3

But this is using Nest right? I do not want to use Nest.

I found that you can use ElasticsearchClient.Msearch();


(Russ Cam) #4

Yes, this is using NEST, the high level client.

To use Elasticsearch.Net low level client with multi search would be

var client = new ElasticLowLevelClient();

client.LowLevel.Msearch<dynamic>(new object[] {
	new { index = "products", type = "product"},
	new { 
		query = new { 
			@bool = new { 
				should = new object [] { 
					new { 
						multi_match = new { 
							type = "best_fields", 
							query = "product query", 
							fields = new [] { "name","name.raw" }
						}
					}
				}
			}
		}
	},
	new { index = "categories", type = "category"},
	new { 
		query = new { 
			@bool = new { 
				should = new object [] { 
					new { 
						multi_match = new { 
							type = "best_fields", 
							query = "category query", 
							fields = new [] { "name","name.raw" }
						}
					}
				}
			}
		}
	}
});

The dynamic generic type parameter on the method is the type into which the response will be deserialized into (which will be an internal JsonObject type when using dynamic).

The low level client by default supports string, byte[], Stream, object, or your own type. The low level client contains a simple json parser that will deserialize the response into an internal JsonObject that can be easily traversed when using dynamic (with all the caveats of bypassing static typing). If you need strongly typed responses, I'd recommend using NEST which exposes all requests and responses as strong types.


(system) #5

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