Elasticsearch To Eloquent Mapping
Glossary of common Elasticsearch queries and their Eloquent equivalents, providing a quick reference for developers coming from Elasticsearch to Laravel’s Eloquent.
Full Text Queries
Match query
Person::whereMatch('description', 'John Smith')->get();
{ "index": "people", "body": { "query": { "match": { "description": { "query": "John Smith", "operator": "and" } } }, "size": 1000 }}
Match phrase query
Person::wherePhrase('description', 'loves espressos')->get();
{ "index": "people", "body": { "query": { "match_phrase": { "description": { "query": "loves espressos" } } }, "size": 1000 }}
Match phrase prefix query
Person::wherePhrasePrefix('description', 'loves es')->get();
{ "index": "people", "body": { "query": { "match_phrase_prefix": { "description": { "query": "loves es" } } }, "size": 1000 }}
Term level queries
Term query
Person::whereExact('name', 'John Smith')->get();
This will only return the documents where the name field is exactly ‘John Smith’. ‘john smith’ or ‘John’ will not be returned.
{ "index": "people", "body": { "query": { "term": { "name.keyword": { "value": "John Smith" } } }, "size": 1000 }}
Terms query
Product::whereIn('status', [1,5,11])->get();
{ "index": "products", "body": { "query": { "terms": { "status": [ 1, 5, 11 ] } }, "size": 1000 }}
Range query
Product::whereBetween('in_stock', [10, 100])->get();
Find all products with an in_stock value between 10 and 100 (including 10 and 100)
{ "index": "products", "body": { "query": { "range": { "status": { "gte": 10, "lte": 100 } } }, "size": 1000 }}
Product::where('status','>=', 3)->take(10)->get();
{ "index": "products", "body": { "query": { "range": { "status": { "gte": 3 } } }, "size": 10 }}
Exists query
Product::whereNotIn('color', ['red','green'])->whereNotNull('color')->get();
{ "index": "products", "body": { "query": { "bool": { "must_not": [ { "terms": { "color.keyword": [ "red", "green" ] } } ], "must": [ { "exists": { "field": "color" } } ] } }, "size": 1000 }}
Product::whereNull('color')->get();
{ "index": "products", "body": { "query": { "bool": { "must_not": [ { "exists": { "field": "color" } } ] } }, "size": 1000 }}
Prefix query
Person::wherePrefix('name', 'John Sm')->get();//OrPerson::whereStartsWith('name', 'John Sm')->get(); //Alias
{ "index": "people", "body": { "query": { "prefix": { "name.keyword": { "value": "John Sm" } } }, "size": 1000 }}
Regex query
Product::whereRegex('color', 'bl(ue)?(ack)?')->get();
The first example will return documents where the color field matches the pattern ‘bl(ue)?(ack)?’, which means it can be ‘blue’ or ‘black’. The second example will return documents where the color field matches the pattern ‘bl…*’, which means it starts with ‘bl’ and has at least three more characters. Both should return Blue or Black from the colors field.
{ "index": "products", "body": { "query": { "regexp": { "color.keyword": { "value": "bl(ue)?(ack)?" } } }, "size": 1000 }}
Fuzzy query
Product::whereFuzzy('description', 'qick brwn fx')->get();
{ "index": "products", "body": { "query": { "fuzzy": { "description": { "value": "qick brwn fx" } } }, "size": 1000 }}
Wildcard query
Product::where('color', 'like', 'bl')->orderBy('color.keyword')->get();
{ "index": "products", "body": { "query": { "wildcard": { "color.keyword": { "value": "*bl*" } } }, "sort": [ { "color.keyword": { "order": "asc" } } ], "size": 1000 }}
Multi-match query
Best Fields
Book::searchTerm('Eric')->orSearchTerm('Lean')->searchTerm('Startup')->get();
{ "index": "books", "body": { "query": { "bool": { "should": [ { "bool": { "must": [ { "multi_match": { "query": "Eric", "type": "best_fields" } } ] } }, { "bool": { "must": [ { "multi_match": { "query": "Lean", "type": "best_fields" } }, { "multi_match": { "query": "Startup", "type": "best_fields" } } ] } } ] } }, "size": 1000 }}
Most Field
Book::searchTermMost('quick brown fox', [ "title", "title.original", "title.shingles" ])->get();
{ "index": "books", "body": { "query": { "multi_match": { "query": "quick brown fox", "type": "most_fields", "fields": [ "title", "title.original", "title.shingles" ] } }, "size": 1000 }}
Phrase
Product::searchPhrase('United States')->orSearchPhrase('United Kingdom')->get();
{ "index": "products", "body": { "query": { "bool": { "should": [ { "bool": { "must": [ { "multi_match": { "query": "United States", "type": "phrase" } } ] } }, { "bool": { "must": [ { "multi_match": { "query": "United Kingdom", "type": "phrase" } } ] } } ] } }, "size": 1000 }}
Phrase Prefix
Person::searchPhrasePrefix('loves espressos and te')->get();
{ "index": "people", "body": { "query": { "multi_match": { "query": "loves espressos and te", "type": "phrase_prefix" } }, "size": 1000 }}
Cross Fields
Person::searchTermCross('Will Smith', [ 'first_name','last_name'],['operator' => 'and'])->get();
{ "index": "people", "body": { "query": { "multi_match": { "query": "Will Smith", "type": "cross_fields", "fields": [ "first_name", "last_name" ], "operator": "and" } }, "_source": [ "*" ] }}
Bool Prefix
Person::searchBoolPrefix('loves espressos and te')->get();
Search for people who have the phrase ‘loves espressos and’ with a prefix of ‘ru’ in the next word in any field. Ex:
- ‘loves espressos and tea’
- ‘loves espressos and tennis’
- ‘loves espressos and tequila’
{ "index": "products", "body": { "query": { "multi_match": { "query": "loves espressos and te", "type": "bool_prefix" } }, "size": 1000 }}
Geo Queries
Geo-bounding box query
// Define the top-left and bottom-right coordinates of the box$topLeft = [-10, 10]; // [latitude, longitude]$bottomRight = [10, -10]; // [latitude, longitude]
// Retrieve UserLogs where 'agent.geo' falls within the defined boxUserLog::where('status', 7)->whereGeoBox('agent.geo', $topLeft, $bottomRight)->get();
{ "index": "user_logs", "body": { "query": { "bool": { "must": [ { "term": { "status": { "value": 7 } } }, { "geo_bounding_box": { "agent.geo": { "top_left": [ -180, 90 ], "bottom_right": [ 180, -90 ] } } } ] } }, "size": 1000 }}
Geo-distance query
// Specify the central point and radius$point = [ 'lat' => 51.509865, 'lon' => -0.118092,]; //or:$point = [51.509865, -0.118092]; // [latitude, longitude]$distance = '20km';
// Retrieve UserLogs with Status 7 where 'agent.geo' is within 20km of center of LondonUserLog::where('status', 7)->whereGeoDistance('agent.geo', $distance, $point)->get();
{ "index": "user_logs", "body": { "query": { "bool": { "must": [ { "term": { "status": { "value": 7 } } }, { "geo_distance": { "agent.geo": [ 51.509865, -0.118092 ], "distance": "20km" } } ] } }, "size": 1000 }}