Search parameters
WARNING
If using the route to perform a search, all parameters must be URL-encoded.
This is not necessary when using the POST
route or one of our .
Query (q)
Parameter: q
Expected value: any string
Default value: null
Sets the search terms.
WARNING
MeiliSearch only considers the first ten words of any given search query. This is necessary in order to deliver a .
Additionally, keep in mind queries go through a normalization process that strips accents and diacritics, as well as making all terms lowercase.
When q
isn’t specified, MeiliSearch performs a placeholder search. A placeholder search returns all searchable documents in an index, modified by any search parameters used and sorted by that index’s custom ranking rules.
If the index has no custom ranking rules, the results are returned in the order of their internal database position.
TIP
Placeholder search is particularly useful when building a .
Example
You can search for films mentioning shifu
by setting the q
parameter:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
client.index('movies').search('shifu')
client.index('movies').search('shifu')
$client->index('movies')->search('shifu');
client.index('movies').search('shifu')
resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.execute()
.await
.unwrap();
This will give you a list of documents that contain your query terms in at least one attribute.
{
"hits": [
{
"id":"50393",
"title":"Kung Fu Panda Holiday",
"poster":"https://image.tmdb.org/t/p/w500/rV77WxY35LuYLOuQvBeD1nyWMuI.jpg",
"overview":"The Winter Feast is Po's favorite holiday. Every year he and his father hang decorations, cook together, and serve noodle soup to the villagers.",
"release_date":1290729600,
"genres":["Animation","Family","TV Movie"]
},
],
"query":"shifu"
}
Phrase search
If you enclose search terms in double quotes ("
), MeiliSearch will only return documents containing those terms in the order they were given. This is called a phrase search.
Phrase searches are case-insensitive and ignore soft separators such as -
, ,
, and :
. Using a hard separator within a phrase search effectively splits it into multiple separate phrase searches: "Octavia.Butler"
will return the same results as "Octavia" "Butler"
.
You can combine phrase search and normal queries in a single search request. In this case, MeiliSearch will first fetch all documents with exact matches to the given phrase(s), and .
Example
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl -X POST 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "\"african american\" horror" }'
client.index('movies')
.search('"african american" horror')
client.index('movies').search('"african american" horror')
$client->index('movies')->search('"african american" horror');
client.index('movies').search('"african american" horror')
resp, err := client.Index("movies").Search("\"african american\" horror", &meilisearch.SearchRequest{})
let results: SearchResults<Movie> = movies
.search()
.with_query("\"african american\" horror")
.execute()
.await
.unwrap();
Offset
Parameter: offset
Expected value: any positive integer
Default value: 0
Sets the starting point in the search results, effectively skipping over a given number of documents.
TIP
This parameter can be used together with limit
in order to paginate results.
Example
If you want to skip the first result in a query, set offset
to 1
:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "offset": 1 }'
client.index('movies').search('shifu', {
offset: 1
})
client.index('movies').search('shifu', {
'offset': 1
})
$client->index('movies')->search('shifu', ['offset' => 1]);
client.index('movies').search('shifu', {
offset: 1
})
resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
Offset: 1,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_offset(1)
.execute()
.await
.unwrap();
Parameter: limit
Expected value: any positive integer
Default value: 20
Sets the maximum number of documents returned by a single query.
TIP
This parameter is often used together with offset
in order to paginate results.
If you want your query to return only two documents, set limit
to 2
:
cURL
JavaScript
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "limit": 2 }'
client.index('movies').search('shifu', {
limit: 2
})
client.index('movies').search('shifu', {
'limit': 2
})
client.index('movies').search('shifu', {
limit: 2
})
resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
Limit: 2,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_limit(2)
.execute()
.await
.unwrap();
Filter
Parameter: filter
Expected value: a filter expression written as a string or an array of strings
Default value: []
Uses filter expressions to refine search results. Attributes used as filter criteria must be added to the filterableAttributes
list.
Example
You can write a filter expression in string syntax using logical connectives:
You can write the same filter as an array:
[["genres = horror", "genres = mystery"], "director = 'Jordan Peele']
You can then use the filter in a search query:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "thriller", "filter": [["genres = Horror", "genres = Mystery"], "director = \"Jordan Peele\""] }'
client.index('movies')
.search('thriller', {
filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
})
client.index('movies').search('thriller', {
'filter': [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
})
$client->index('movies')->search('thriller', ['filter' => [['genres:Horror', 'genres:Mystery']], 'director' => "Jordan Peele"]);
client.index('movies').search('thriller', {
filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
})
resp, err := client.Index("movies").Search("thriller", &meilisearch.SearchRequest{
Filter: [][]string{
[]string{"genres = Horror", "genres = Mystery"},
[]string{"director = \"Jordan Peele\""},
})
let results: SearchResults<Movie> = movies.search()
.with_query("thriller")
.with_filter("(genres = Horror AND genres = Mystery) OR director = \"Jordan Peele\"")
.execute()
.await
.unwrap();
Facets distribution
Parameter: facetsDistribution
Expected value: an array of attribute
s or ["*"]
Default value: null
Returns the number of documents matching the current search query for each given facet.
This parameter can take two values:
- An array of attributes:
facetsDistribution=["attributeA", "attributeB", …]
- An asterisk—this will return a count for all facets present in
filterableAttributes
NOTE
If an attribute used on facetsDistribution
has not been added to the filterableAttributes
list, it will be ignored.
Returned fields
When facetsDistribution
is set, the search results object contains two additional fields:
facetsDistribution
: The number of remaining candidates for each specified facetexhaustiveFacetsCount
: Atrue
orfalse
value indicating whether the count is exact (true
) or approximate (false
)
exhaustiveFacetsCount
is false
when the search matches contain too many different values for the given facetName
s. In this case, MeiliSearch stops the distribution count to prevent slowing down the request.
WARNING
exhaustiveFacetsCount
is not currently implemented and will always return false
.
Example
Given a movie database, suppose that you want to know the number of Batman
movies per genre:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl \
-X POST 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "Batman", "facetsDistribution": ["genres"] }'
client.index('movies')
.search('Batman', {
facetsDistribution: ['genres']
})
client.index('movies').search('Batman', {
'facetsDistribution': ['genres']
})
$client->index('movies')->search('Batman', ['facetsDistribution' => ['genres']]);
client.index('movies').search('Batman', {
facetsDistribution: ['genres']
})
resp, err := client.Index("movies").Search("Batman", &meilisearch.SearchRequest{
FacetsDistribution: []string{
"genres",
},
})
let results: SearchResults<Movie> = movies.search()
.with_query("Batman")
.with_facets_distribution(Selectors::Some(&["genres"]))
.execute()
.await
.unwrap();
let genres: &HashMap<String, usize> = results.facets_distribution.unwrap().get("genres").unwrap();
You would get the following response:
{
…
"nbHits": 1684,
"query": "Batman",
"exhaustiveFacetsCount": false,
"facetsDistribution": {
"genres": {
"action": 273,
"animation": 118,
"adventure": 132,
"fantasy": 67,
"comedy": 475,
"mystery": 70,
"thriller": 217,
}
}
}
Parameter: attributesToRetrieve
Expected value: an array of attribute
s or ["*"]
Default value: ["*"]
Configures which attributes will be retrieved in the returned documents.
If no value is specified, attributesToRetrieve
uses the , which by default contains all attributes found in the documents.
To get only the overview
and title
fields, set attributesToRetrieve
to ["overview", "title"]
.
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "attributesToRetrieve": ["overview", "title"] }'
client.index('movies').search('shifu', {
attributesToRetrieve: ['overview', 'title']
})
client.index('movies').search('shifu', {
'attributesToRetrieve': ['overview', 'title']
})
$client->index('movies')->search('shifu', ['attributesToRetrieve' => ['overview', 'title']]);
resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
AttributesToRetrieve: []string{"overview", "title"},
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_attributes_to_retrieve(Selectors::Some(&["overview", "title"]))
.execute()
.await
.unwrap();
Attributes to crop
Parameter: attributesToCrop
Expected value: an array of attributes
An attribute is the name of a field, like a key.
Ex: "title": "Batman"
In the example above, “title” is the attribute.
Crops the selected attributes’ values in the returned results to the length indicated by the parameter.
When this parameter is set, a field called _formatted
will be added to hits
. The cropped version of each document will be available there.
Optionally, you can indicate a custom crop length for any of the listed attributes: attributesToCrop=["attributeNameA:25", "attributeNameB:150"]
. The custom crop length set in this way has priority over the cropLength
parameter.
Instead of supplying individual attributes
, you can provide ["*"]
as a value: attributesToCrop=["*"]
. This will crop the values of all attributes present in attributesToRetrieve
.
Cropping starts at the first occurrence of the search query. It only keeps cropLength
characters on each side of the first match, rounded to match word boundaries.
If no query word is present in the cropped field, the crop will start from the first word.
Example
If you use shifu
as a search query and set the value of the cropLength
parameter to 10
:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "attributesToCrop": ["overview"], "cropLength": 10 }'
client.index('movies').search('shifu', {
attributesToCrop: ['overview'],
cropLength: 10
})
client.index('movies').search('shifu', {
'attributesToCrop': ['overview'],
'cropLength': 10
})
$client->index('movies')->search('shifu', ['attributesToCrop' => ['overview'], 'cropLength' => 10]);
attributesToCrop: ['overview'],
cropLength: 10
})
resp, err := client.Index("movies").Search("shifu" &meilisearch.SearchRequest{
CropLength: 10,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_attributes_to_crop(Selectors::Some(&[("overview", None)]))
.with_crop_length(10)
.execute()
.await
.unwrap();
// Get the formatted results
let formatted_results: Vec<&Movie> = results.hits.iter().map(|r| r.formatted_result.as_ref().unwrap()).collect();
You will get the following response with the cropped text in the _formatted
object:
{
"id": "50393",
"title": "Kung Fu Panda Holiday",
"poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
"overview": "The Winter Feast is Po's favorite holiday. Every year he and his father hang decorations, cook together, and serve noodle soup to the villagers. But this year Shifu informs Po that as Dragon Warrior, it is his duty to host the formal Winter Feast at the Jade Palace. Po is caught between his obligations as the Dragon Warrior and his family traditions: between Shifu and Mr. Ping.",
"release_date": 1290729600,
"_formatted": {
"id": "50393",
"title": "Kung Fu Panda Holiday",
"poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
"overview": "this year Shifu informs",
"release_date": 1290729600
}
}
Crop length
Parameter: cropLength
Expected value: a positive integer
Default value: 200
Configures the number of characters to keep on each side of the matching query term when using the parameter. Note that this means there can be up to 2 * cropLength
characters in the cropped field.
If attributesToCrop
is not configured, cropLength
has no effect on the returned results.
Parameter: attributesToHighlight
Expected value: an array of attributes
An attribute is the name of a field, like a key.
Ex: "title": "Batman"
In the example above, “title” is the attribute.
or ["*"]
Default value: null
Highlights matching query terms in the given attributes. When this parameter is set, the _formatted
object is added to the response for each document, within which you can find the highlighted text.
Values can be supplied as an array of attributes: attributesToHighlight=["attributeA", "attributeB"]
.
Alternatively, you can provide ["*"]
as a value: attributesToHighlight=["*"]
. In this case, all the attributes present in attributesToRetrieve
will be assigned to attributesToHighlight
.
TIP
The highlighting performed by this parameter consists of wrapping matching query terms in <em>
tags. Neither this tag nor this behavior can be modified.
If a different type of highlighting is desired, we recommend the matches
parameter, which provides much finer control over the output.
Example
If you wanted to highlight query matches that appear within the overview
attribute:
cURL
JavaScript
Python
PHP
Ruby
Go
Rust
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "winter feast", "attributesToHighlight": ["overview"] }'
client.index('movies').search('winter feast', {
attributesToHighlight: ['overview']
})
client.index('movies').search('winter feast', {
'attributesToHighlight': ['overview']
})
$client->index('movies')->search('winter feast', ['attributesToHighlight' => ['overview']]);
client.index('movies').search('winter feast', {
attributesToHighlight: ['overview']
})
resp, err := client.Index("movies").Search("winter feast", &meilisearch.SearchRequest{
AttributesToHighlight: []string{"overview"},
})
let results: SearchResults<Movie> = movies.search()
.with_query("winter feast")
.with_attributes_to_highlight(Selectors::Some(&["overview"]))
.execute()
.await
.unwrap();
// Get the formatted results
let formatted_results: Vec<&Movie> = results.hits.iter().map(|r| r.formatted_result.as_ref().unwrap()).collect();
You would get the following response with the highlighted version in the _formatted
object:
{
"id": "50393",
"title": "Kung Fu Panda Holiday",
"poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
"overview": "The Winter Feast is Po's favorite holiday. Every year he and his father hang decorations, cook together, and serve noodle soup to the villagers. But this year Shifu informs Po that as Dragon Warrior, it is his duty to host the formal Winter Feast at the Jade Palace. Po is caught between his obligations as the Dragon Warrior and his family traditions: between Shifu and Mr. Ping.",
"release_date": 1290729600,
"_formatted": {
"id": "50393",
"title": "Kung Fu Panda Holiday",
"poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
"overview": "The Winter Feast is Po's favorite holiday. Every year he and his father hang decorations, cook together, and serve noodle soup to the villagers. But this year <em>Shifu</em> informs Po that as Dragon Warrior, it is his duty to host the formal Winter Feast at the Jade Palace. Po is caught between his obligations as the Dragon Warrior and his family traditions: between <em>Shifu</em> and Mr. Ping.",
"release_date": 1290729600
}
}
Matches
Parameter: matches
Expected value: true
or false
Default value: false
Adds an object to the search response (_matchesInfo
) containing the location of each occurrence of queried terms across all fields. This is useful when you need more control than offered by our .
The beginning of a matching term within a field is indicated by start
, and its length by length
.
WARNING
start
and length
are measured in bytes and not the number of characters. For example, ü
represents two bytes but one character.
matchesInfo
cannot be used with arrays and objects, only strings.
Example
If you set matches
to true
and search for shifu
:
cURL
JavaScript
Python
PHP
Ruby
Go
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "winter feast", "matches": true }'
client.index('movies').search('winter feast', {
matches: true
})
client.index('movies').search('winter feast', {
'matches': 'true'
})
$client->index('movies')->search('winter feast', ['attributesToHighlight' => ['overview'], 'matches' => true]);
client.index('movies').search('winter feast', {
matches: true
})
resp, err := client.Index("movies").Search("winter feast", &meilisearch.SearchRequest{
Matches: true,
})
You would get the following response with information about the matches in the _matchesInfo
object:
{
"id": "50393",
"title": "Kung Fu Panda Holiday",
"poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
"overview": "The Winter Feast is Po's favorite holiday. Every year he and his father hang decorations, cook together, and serve noodle soup to the villagers. But this year Shifu informs Po that as Dragon Warrior, it is his duty to host the formal Winter Feast at the Jade Palace. Po is caught between his obligations as the Dragon Warrior and his family traditions: between Shifu and Mr. Ping.",
"release_date": 1290729600,
"_matchesInfo": {
"overview": [
{
"start": 159,
"length": 5
},
{
"start": 361,
"length": 5
}
]