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