OpenSearch To Eloquent Mapping
This content is for v1/2. Switch to the latest version for up-to-date documentation.
Glossary of common OpenSearch queries and their Eloquent equivalents, providing a quick reference for developers coming from OpenSearch to Laravel’s Eloquent.
Full Text Queries
Match query
$products = Product::where('manufacturer.country', 'England')->take(10)->get();
{ "index": "products", "body": { "query": { "match": { "manufacturer.country": "England" } }, "_source": [ "*" ] }, "size": 10}
Match phrase query
return Person::wherePhrase('description', 'loves espressos')->get();
{ "index": "people", "body": { "query": { "match_phrase": { "description": "loves espressos" } }, "_source": [ "*" ] }}
Match phrase prefix query
return Person::wherePhrasePrefix('description', 'loves es')->get();
{ "index": "people", "body": { "query": { "match_phrase_prefix": { "description": "loves es" } }, "_source": [ "*" ] }}
Term level queries
Term query
return 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": "John Smith" } }, "_source": [ "*" ] }}
Terms query
$products = Product::whereIn('status', [1,5,11])->get();
{ "index": "products", "body": { "query": { "terms": { "status": [ 1, 5, 11 ] } }, "_source": [ "*" ] }}
Range query
$products = 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": { "in_stock": { "gte": 10, "lte": 100 } } }, "_source": [ "*" ] }}
$products = Product::where('status','>=', 3)->take(10)->get();
{ "index": "products", "body": { "query": { "range": { "status": { "gte": 3 } } }, "_source": [ "*" ] }, "size": 10}
Exists query
$products = Product::whereNotIn('color', ['red','green'])->whereNotNull('color')->get();
{ "index": "products", "body": { "query": { "bool": { "must": [ { "bool": { "must_not": { "terms": { "color": [ "red", "green" ] } } } }, { "exists": { "field": "color" } } ] } }, "_source": [ "*" ] }}
$products = Product::whereNull('color')->get();
{ "index": "products", "body": { "query": { "bool": { "must_not": [ { "exists": { "field": "color" } } ] } }, "_source": [ "*" ] }}
Fuzzy query
- Not directly supported in V4, but can be implemented using multi_match queries, see: search queries as Fuzzy
Prefix query
- Not directly supported in V4, but can be implemented using multi_match queries:
Wildcard query
$products = Product::where('color', 'like', 'bl')->orderBy('color.keyword')->get();
{ "index": "products", "body": { "query": { "query_string": { "query": "color:*bl*" } }, "_source": [ "*" ], "sort": [ { "color.keyword": { "order": "asc" } } ] }}
Multi-match query
Best Fields
$results = Book::searchTerm('Eric')->orSearchTerm('Lean')->searchTerm('Startup')->get();
Search for books that contain ‘Eric’ or (‘Lean’ and ‘Startup’)
{ "index": "books", "body": { "query": { "bool": { "should": [ { "bool": { "must": [ { "multi_match": { "query": "Eric", "type": "best_fields", "fields": [ "*" ] } } ] } }, { "bool": { "must": [ { "multi_match": { "query": "Lean", "type": "best_fields", "fields": [ "*" ] } }, { "multi_match": { "query": "Startup", "type": "best_fields", "fields": [ "*" ] } } ] } } ] } }, "_source": [ "*" ] }}
Most Field
$results = Book::searchTermMost('quick brown fox', [ "title", "title.original", "title.shingles" ])->get();
Search for books that contain ‘quick brown fox’ in the ‘title’, ‘title.original’, or ‘title.shingles’ fields
{ "index": "books", "body": { "query": { "multi_match": { "query": "quick brown fox", "type": "most_fields", "fields": [ "title", "title.original", "title.shingles" ] } }, "_source": [ "*" ] }}
Phrase
Product::searchPhrase('United States')->orSearchPhrase('United Kingdom')->get();
{ "index": "products", "body": { "query": { "bool": { "should": [ { "bool": { "must": [ { "multi_match": { "query": "United States", "type": "phrase", "fields": [ "*" ] } } ] } }, { "bool": { "must": [ { "multi_match": { "query": "United Kingdom", "type": "phrase", "fields": [ "*" ] } } ] } } ] } }, "_source": [ "*" ] }}
Phrase Prefix
$results = Person::searchPhrasePrefix('loves espressos and te')->get();
{ "index": "people", "body": { "query": { "multi_match": { "query": "loves espressos and te", "type": "phrase_prefix", "fields": [ "*" ] } }, "_source": [ "*" ] }}
Cross Fields
$results = 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
$results = 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": "people", "body": { "query": { "multi_match": { "query": "loves espressos and te", "type": "bool_prefix", "fields": [ "*" ] } }, "_source": [ "*" ] }}
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 box$logs = UserLog::where('status', 7)->filterGeoBox('agent.geo', $topLeft, $bottomRight)->get();
{ "index": "user_logs", "body": { "query": { "bool": { "must": [ { "match": { "status": 7 } } ], "filter": { "geo_bounding_box": { "agent.geo": { "top_left": [ -10, 10 ], "bottom_right": [ 10, -10 ] } } } } }, "_source": [ "*" ] }}
Geo-distance query
// Specify the central point and radius$point = [0, 0]; // [latitude, longitude]$distance = '20km';
// Retrieve UserLogs where 'agent.geo' is within 20km of the specified point$logs = UserLog::where('status', 7)->filterGeoPoint('agent.geo', $distance, $point)->get();
{ "index": "user_logs", "body": { "query": { "bool": { "must": [ { "match": { "status": 7 } } ], "filter": { "geo_distance": { "distance": "20km", "agent.geo": { "lat": 0, "lon": 0 } } } } }, "_source": [ "*" ] }}