1[[search_operations]] 2== Search Operations 3 4Well...it isn't called elasticsearch for nothing! Let's talk about search operations in the client. 5 6The client gives you full access to every query and parameter exposed by the REST API, following the naming scheme as 7much as possible. Let's look at a few examples so you can become familiar with the syntax. 8 9=== Match Query 10 11Here is a standard curl for a Match query: 12 13[source,shell] 14---- 15curl -XGET 'localhost:9200/my_index/_search' -d '{ 16 "query" : { 17 "match" : { 18 "testField" : "abc" 19 } 20 } 21}' 22---- 23{zwsp} + 24 25And here is the same query constructed in the client: 26 27[source,php] 28---- 29$params = [ 30 'index' => 'my_index', 31 'body' => [ 32 'query' => [ 33 'match' => [ 34 'testField' => 'abc' 35 ] 36 ] 37 ] 38]; 39 40$results = $client->search($params); 41---- 42{zwsp} + 43 44Notice how the structure and layout of the PHP array is identical to that of the JSON request body. This makes it very 45simple to convert JSON examples into PHP. A quick method to check your PHP array (for more complex examples) is to 46encode it back to JSON and check by eye: 47 48[source,php] 49---- 50$params = [ 51 'index' => 'my_index', 52 'body' => [ 53 'query' => [ 54 'match' => [ 55 'testField' => 'abc' 56 ] 57 ] 58 ] 59]; 60 61print_r(json_encode($params['body'])); 62 63 64{"query":{"match":{"testField":"abc"}}} 65---- 66{zwsp} + 67 68 69.Using Raw JSON 70**** 71Sometimes it is convenient to use raw JSON for testing purposes, or when migrating from a different system. You can 72use raw JSON as a string in the body, and the client will detect this automatically: 73 74[source,php] 75---- 76$json = '{ 77 "query" : { 78 "match" : { 79 "testField" : "abc" 80 } 81 } 82}'; 83 84$params = [ 85 'index' => 'my_index', 86 'body' => $json 87]; 88 89$results = $client->search($params); 90---- 91**** 92{zwsp} + 93 94Search results follow the same format as Elasticsearch search response, the only difference is that the JSON response is 95serialized back into PHP arrays. Working with the search results is as simple as iterating over the array values: 96 97[source,php] 98---- 99$params = [ 100 'index' => 'my_index', 101 'body' => [ 102 'query' => [ 103 'match' => [ 104 'testField' => 'abc' 105 ] 106 ] 107 ] 108]; 109 110$results = $client->search($params); 111 112$milliseconds = $results['took']; 113$maxScore = $results['hits']['max_score']; 114 115$score = $results['hits']['hits'][0]['_score']; 116$doc = $results['hits']['hits'][0]['_source']; 117---- 118{zwsp} + 119 120=== Bool Queries 121 122Bool queries can be easily constructed using the client. For example, this query: 123[source,shell] 124---- 125curl -XGET 'localhost:9200/my_index/_search' -d '{ 126 "query" : { 127 "bool" : { 128 "must": [ 129 { 130 "match" : { "testField" : "abc" } 131 }, 132 { 133 "match" : { "testField2" : "xyz" } 134 } 135 ] 136 } 137 } 138}' 139---- 140{zwsp} + 141 142Would be structured like this (Note the position of the square brackets): 143[source,php] 144---- 145$params = [ 146 'index' => 'my_index', 147 'body' => [ 148 'query' => [ 149 'bool' => [ 150 'must' => [ 151 [ 'match' => [ 'testField' => 'abc' ] ], 152 [ 'match' => [ 'testField2' => 'xyz' ] ], 153 ] 154 ] 155 ] 156 ] 157]; 158 159$results = $client->search($params); 160---- 161{zwsp} + 162 163Notice that the `must` clause accepts an array of arrays. This will be serialized into an array of JSON objects internally, 164so the final resulting output will be identical to the curl example. For more details about arrays vs objects in PHP, 165see <<php_json_objects, Dealing with JSON Arrays and Objects in PHP>>. 166 167=== A more complicated example 168 169Let's construct a slightly more complicated example: a boolean query that contains both a filter and a query. 170This is a very common activity in elasticsearch queries, so it will be a good demonstration. 171 172The curl version of the query: 173 174[source,shell] 175---- 176curl -XGET 'localhost:9200/my_index/_search' -d '{ 177 "query" : { 178 "bool" : { 179 "filter" : { 180 "term" : { "my_field" : "abc" } 181 }, 182 "should" : { 183 "match" : { "my_other_field" : "xyz" } 184 } 185 } 186 } 187}' 188---- 189{zwsp} + 190 191And in PHP: 192 193[source,php] 194---- 195$params = [ 196 'index' => 'my_index', 197 'body' => [ 198 'query' => [ 199 'bool' => [ 200 'filter' => [ 201 'term' => [ 'my_field' => 'abc' ] 202 ], 203 'should' => [ 204 'match' => [ 'my_other_field' => 'xyz' ] 205 ] 206 ] 207 ] 208 ] 209]; 210 211 212$results = $client->search($params); 213---- 214{zwsp} + 215 216 217=== Scrolling 218 219The Scrolling functionality of Elasticsearch is used to paginate over many documents in a bulk manner, such as exporting 220all the documents belonging to a single user. It is more efficient than regular search because it doesn't need to maintain 221an expensive priority queue ordering the documents. 222 223Scrolling works by maintaining a "point in time" snapshot of the index which is then used to page over. 224This window allows consistent paging even if there is background indexing/updating/deleting. First, you execute a search 225request with `scroll` enabled. This returns a "page" of documents, and a scroll_id which is used to continue 226paginating through the hits. 227 228More details about scrolling can be found in the https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html[Link: reference documentation]. 229 230This is an example which can be used as a template for more advanced operations: 231 232[source,php] 233---- 234$client = ClientBuilder::create()->build(); 235$params = [ 236 'scroll' => '30s', // how long between scroll requests. should be small! 237 'size' => 50, // how many results *per shard* you want back 238 'index' => 'my_index', 239 'body' => [ 240 'query' => [ 241 'match_all' => new \stdClass() 242 ] 243 ] 244]; 245 246// Execute the search 247// The response will contain the first batch of documents 248// and a scroll_id 249$response = $client->search($params); 250 251// Now we loop until the scroll "cursors" are exhausted 252while (isset($response['hits']['hits']) && count($response['hits']['hits']) > 0) { 253 254 // ** 255 // Do your work here, on the $response['hits']['hits'] array 256 // ** 257 258 // When done, get the new scroll_id 259 // You must always refresh your _scroll_id! It can change sometimes 260 $scroll_id = $response['_scroll_id']; 261 262 // Execute a Scroll request and repeat 263 $response = $client->scroll([ 264 'scroll_id' => $scroll_id, //...using our previously obtained _scroll_id 265 'scroll' => '30s' // and the same timeout window 266 ] 267 ); 268} 269---- 270