How to execute multi search msearch query in ElasticSearch with PHP

How to execute multi search msearch query in ElasticSearch with PHP banner

ElasticSearch gives you the ability to execute multiple queries in a single request by using the Multi-Search API

The API is pretty straightforward

GET my-index-000001/_msearch
{ }
{"query" : {"match" : { "message": "this is a test"}}}
{"index": "my-index-000002"}
{"query" : {"match_all" : {}}}

The payload should follow the INDEX -> QUERY pair separated by new lines.

Now, if you want to use multi-search API with the PHP, that's a different story.

I couldn't find any documentation about this method, and I've struggled a bit to make it work. I'm sharing this with you to save you some time.

I'm using ElasticSearch version 8.9.1 client and server. Here is s simple msearch example.

// ....

$result = $client->msearch(['index' => 'index_name', 'body' => [
   '{"index": "index_name"}' . "\n" .
   '{"query" : {"match_all" : {}}}' . "\n" .
   '{"index": "index_name"}' . "\n" .
   '{"query" : {"match" : { "message": "this is a test"}}}' . "\n"

The only documentation about this method that you can find is in the method itself.


// ..
	 * Allows to execute several search operations in one request.
	 * @see
	 * @param array{
	 *     index: list, //  A comma-separated list of index names to use as default
	 *     search_type: enum, // Search operation type
	 *     max_concurrent_searches: number, // Controls the maximum number of concurrent searches the multi search api will execute
	 *     typed_keys: boolean, // Specify whether aggregation and suggester names should be prefixed by their respective types in the response
	 *     pre_filter_shard_size: number, // A threshold that enforces a pre-filter roundtrip to prefilter search shards based on query rewriting if the number of shards the search request expands to exceeds the threshold. This filter roundtrip can limit the number of shards significantly if for instance a shard can not match any documents based on its rewrite method ie. if date filters are mandatory to match but the shard bounds and the query are disjoint.
	 *     max_concurrent_shard_requests: number, // The number of concurrent shard requests each sub search executes concurrently per node. This value should be used to limit the impact of the search on the cluster in order to limit the number of concurrent shard requests
	 *     rest_total_hits_as_int: boolean, // Indicates whether should be rendered as an integer or an object in the rest search response
	 *     ccs_minimize_roundtrips: boolean, // Indicates whether network round-trips should be minimized as part of cross-cluster search requests execution
	 *     pretty: boolean, // Pretty format the returned JSON response. (DEFAULT: false)
	 *     human: boolean, // Return human readable values for statistics. (DEFAULT: true)
	 *     error_trace: boolean, // Include the stack trace of returned errors. (DEFAULT: false)
	 *     source: string, // The URL-encoded request definition. Useful for libraries that do not accept a request body for non-POST requests.
	 *     filter_path: list, // A comma-separated list of filters used to reduce the response.
	 *     body: array, // (REQUIRED) The request definitions (metadata-search request definition pairs), separated by newlines
	 * } $params
	 * @throws NoNodeAvailableException if all the hosts are offline
	 * @throws ClientResponseException if the status code of response is 4xx
	 * @throws ServerResponseException if the status code of response is 5xx
	 * @return Elasticsearch|Promise
	public function msearch(array $params = [])
// ..

To be honest, I expected to pass an array instead of a string separated by a new line.