Search Parameters
Search parameters let the user customize their search request.
Query Parameter | Description | Default Value |
---|---|---|
q | Query string | “” |
offset | Number of documents to skip | 0 |
limit | Maximum number of documents returned | 20 |
filters | Filter queries by an attribute value | null |
facetFilters | Facet names and values to filter on | null |
facetsDistribution | Facets for which to retrieve the matching count | null |
attributesToRetrieve | Attributes to display in the returned documents | [“*”] |
attributesToCrop | Attributes whose values have to be cropped | null |
cropLength | Length used to crop field values | 200 |
attributesToHighlight | Attributes whose values will contain highlighted matching terms | null |
matches | Defines whether an object that contains information about the matches should be returned or not | false |
Query (q)
This is the string used by the search engine to find relevant documents. Search queries are tokenized.
WARNING
MeiliSearch only considers the first ten words of any given search query. This is necessary in order to deliver a fast type-as-you-search experience in a consistent way.
q=<String>
<String>
(String)The query string.
Example
Suppose you would like to search shifu
in a movie database. You would send the following:
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu" }'
client.index('movies').search('shifu')
client.index('movies').search('shifu')
$client->index('movies')->search('shifu');
index.search('shifu')
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.execute()
.await
.unwrap();
Placeholder Search
When q
isn’t specified, a placeholder search is performed. Placeholder search allows you to find documents without providing any search terms.
Placeholder search returns the documents that best match other search parameters, sorted according to that index’s ranking rules. This feature also supports faceting and filtering
Offset
A number of documents to skip.
offset=<Integer>
<Integer>
(Optional, positive integer, defaults to0
)If the value of the parameter
offset
is n, n first documents to skip. This is helpful for pagination.
Example
If you want to skip the first document, set offset
to 1
.
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]);
index.search('shifu', {
offset: 1
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
Offset: 1,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_offset(1)
.execute()
.await
.unwrap();
Limit
Set a limit to the number of documents returned by search queries.
limit=<Integer>
<Integer>
(Optional, positive integer, defaults to20
)If the value of the parameter
limit
is n, there will be n documents in the search query response. This is helpful for pagination.
Example
If you want to get only two documents, set limit
to 2
.
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' => 1]);
index.search('shifu', {
limit: 2
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
Limit: 2,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_limit(2)
.execute()
.await
.unwrap();
Filters
filters=<String>
Specify a filter to be used with the query. See our dedicated guide.
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "n", "filters": "title = Nightshift" }'
client.index('movies').search('n', {
filters: 'title = Nightshift'
})
client.index('movies').search('n', {
'filters': 'title = Nightshift'
})
$client->index('movies')->search('n', ['filters' => 'title = Nightshift']);
index.search('n', {
filters: 'title = Nightshift'
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "n",
Filters: "title = Nightshift",
})
let results: SearchResults<Movie> = movies.search()
.with_query("n")
.with_filters("title = Nightshift")
.execute()
.await
.unwrap();
{
"id": "569367",
"title": "Nightshift",
"poster": "https://image.tmdb.org/t/p/w1280/peOeFl8ZTBTCERz5XQZAjYbXYsQ.jpg",
"overview": "Amy begins her first night shift in a hotel with a murderous past. Witnessing terrifying events and trapped within a loop, Amy must find a way to escape the flesh obsessed murderer and save residents of the hotel.",
"release_date": 1536282000
}
The parameter should be URL-encoded.
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "filters": "title=\"Kung Fu Panda\"" }'
client.index('movies').search('n', {
filters: 'title="Kung Fu Panda"'
})
client.index('movies').search('n', {
'filters': 'title = "Kung Fu Panda"'
})
$client->index('movies')->search('shifu', ['filters' => 'title="Kung Fu Panda"']);
index.search('n', {
filters: 'title="Kung Fu Panda"'
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "n",
Filters: "title=\"Kung Fu Panda\"",
})
let results: SearchResults<Movie> = movies.search()
.with_query("n")
.with_filters(r#"title = "Kung Fu Panda""#)
.execute()
.await
.unwrap();
Facet filters
If you have set up faceted attributes, you can filter on facets to narrow down your results based on criteria.
facetFilters=["facetName:facetValue"]
or facetFilters=[["facetName:facetValue"]]
or a mix of both facetFilters=["facetName1:facetValue1", ["facetName2:facetValue2"]]
["facetName1:facetValue1", ["facetName2:facetValue2"]]
(Array of array of strings or single strings, defaults tonull
)Both types of array contain the facet names and values to filter on.
A valid array must be an array that contains either a list of strings or arrays of strings and can mix both (e.g.["director:Mati Diop", ["genres:Comedy", "genres:Romance"]]
).facetName
: The name (the attribute) of a field used as a facet (e.g.director
,genres
).facetValue
: The value of this facet to filter results on (e.g.Tim Burton
,Mati Diop
,Comedy
,Romance
).
Facet filters also support logical connectives by using inner and outer array elements.
Learn more about facet filters in the dedicated guide
Example
Suppose you have declared director
and genres
as faceted attributes, and you want to get movies matching “thriller” classified as either horror or mystery and directed by Jordan Peele.
("genres:Horror" OR "genres:Mystery") AND "director:Jordan Peele"
Querying on “thriller”, the above example results in the following CURL command:
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "thriller", "facetFilters": [["genres:Horror", "genres:Mystery"], "director:Jordan Peele"] }'
client.index('movies')
.search('thriller', {
facetFilters: [['genres:Horror', 'genres:Mystery'], 'director:Jordan Peele']
})
client.index('movies').search('thriller', {
'facetFilters': [['genres:Horror', 'genres:Mystery'], 'director:Jordan Peele']
})
$client->index('movies')->search('thriller', ['facetFilters' => [['genres:Horror', 'genres:Mystery']], 'director' => "Jordan Peele"]);
index.search('thriller', {
facetFilters: [['genres:Horror', 'genres:Mystery'], 'director:Jordan Peele']
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "thriller",
FacetFilters: [][]string{
[]string{"genres:Horror", "genres:Mystery"},
[]string{"director:Jordan Peele"},
},
})
let results: SearchResults<Movie> = movies.search()
.with_query("thriller")
.with_facet_filters(&[&["genres:Horror", "genres:Mystery"], &["director:Jordan Peele"]])
.execute()
.await
.unwrap();
And you would get the following response:
{
"hits": [
{
"id": 458723,
"title": "Us",
"director": "Jordan Peele",
"tagline": "Watch yourself",
"genres": [
"Thriller",
"Horror",
"Mystery"
],
"overview": "Husband and wife Gabe and Adelaide Wilson take their kids to their beach house expecting to unplug and unwind with friends. But as night descends, their serenity turns to tension and chaos when some shocking visitors arrive uninvited.",
},
{
"id": 419430,
"title": "Get Out",
"director": "Jordan Peele",
"genres": [
"Mystery",
"Thriller",
"Horror"
],
"overview": "Chris and his girlfriend Rose go upstate to visit her parents for the weekend. At first, Chris reads the family's overly accommodating behavior as nervous attempts to deal with their daughter's interracial relationship, but as the weekend progresses, a series of increasingly disturbing discoveries lead him to a truth that he never could have imagined.",
}
],
...
"query": "thriller"
}
The facets distribution
If you have set up faceted attributes, you can retrieve the count of matching terms for each facets.
facetsDistribution=[<facetName>, <facetName>, ...]
This attribute can take two values:
[<facetName>, <facetName>, ...]
(Array of strings)An array of strings that contains the facets for which to retrieve the matching count. The number of remaining candidates for each specified facet is returned.
If a facet name doesn’t exist, it will be ignored.["*"]
In that case, a count for all facets is returned.
Returned fields
If the facetsDistribution
parameter has been set, the returned results will contain two additional fields:
facetsDistribution
: The number of remaining candidates for each specified facet.exhaustiveFacetsCount
:
Returnstrue
if the count in each facet value is exhaustive (exact count for each facet value).
Otherwise, returnsfalse
if this count is approximative (approximative count for each facet value).
The approximative facet count happens when there are too many documents in too many different facet values. In which case, MeiliSearch stops the distribution count to prevent considerably slowing down the request.
Learn more about facet distribution in the dedicated guide
Example
Given a movie database, suppose that you want to know what the number of Batman movies per genre is. You would use the following CURL command:
curl --get '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']]);
index.search('Batman', {
facetsDistribution: ['genres']
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "Batman",
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();
And you would get the following response:
{
"hits": [
...
],
...
"nbHits": 1684,
"query": "Batman",
"exhaustiveFacetsCount": true,
"facetsDistribution": {
"genres": {
"action": 273,
"animation": 118,
"adventure": 132,
"fantasy": 67,
"comedy": 475,
"mystery": 70,
"thriller": 217,
}
}
}
Attributes to Retrieve
Attributes to display in the returned documents.
attributesToRetrieve=<Attribute>,<Attribute>,...
<Attribute>
(Optional, string, Defaults to['*']
)Comma-separated list of attributes whose fields will be present in the returned documents.
Defaults to to the displayedAttributes list which contains by default all attributes found in the documents.
Example
If you want to get only the overview
and title
field and not the other fields, set attributesToRetrieve
to overview,title
.
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']]);
index.search('shifu', {
attributesToRetrieve: ['overview', 'title']
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
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
Attributes whose values will be cropped if they contain a matched query word.
attributesToCrop=<Attribute:Croplength>,<Attribute:Croplength>,...
Attribute can have two values:
<Attribute>
OR<Attribute:Croplength>
(Optional, string, defaults to empty)Comma-separated list of attributes whose values will be cropped if they contain a matched query word.
Each attribute can be joined by an optionalcropLength
that overwrites the cropLength parameter.['*']
In this case, all the attributes present in
attributesToRetrieve
will be assigned toattributesToCrop
.
In the case a matched query word is found, the field’s value will be cropped around the first matched query word according to the cropLength
value (default 200
see cropLength to change this value).
Some working examples:
attributesToCrop=overview
attributesToCrop=overview:20
attributesToCrop=*,overview:20,title:0
TIP
This is especially useful when you have to display content on the front-end in a specific way.
Cropping start at the first occurrence of the search query. It only keeps cropLength
chars on each side of the first match, rounded to match word boundaries.
Example
If you input shifu
as a search query and set the value of the parameter cropLength
to 10
:
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]);
index.search('shifu', {
attributesToCrop: ['overview'],
cropLength: 10
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
AttributesToCrop: []string{"overview"},
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 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": "this year Shifu informs",
"release_date": 1290729600
}
}
Crop Length
cropLength=<Integer>
(Optional, positive integer, defaults to 200
)
Number of characters to keep on each side of the start of the matching word. See attributesToCrop.
Attributes to Highlight
Attributes whose values will contain highlighted matching query words.
attributesToHighlight=[<Attribute>,<Attribute>,...]
Attribute can have two values:
<Attribute>
(Optional, string, defaults to empty)Comma-separated list of attributes. Every matching query words in the given attribute field will be wrapped around an
<em>
tag."*"
In this case, all the attributes present in
attributesToRetrieve
will be assigned toattributesToHighlight
.
Every matching string sequence in the given attribute’s field will be wrapped around an <em>
tag.
Some working examples:
attributesToHighlight=overview
attributesToHighlight=*,overview
Example
If you choose to highlight the content of overview
:
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "attributesToHighlight": ["overview"] }'
client.index('movies').search('shifu', {
attributesToHighlight: ['overview']
})
client.index('movies').search('shifu', {
'attributesToHighlight': ['overview']
})
$client->index('movies')->search('shifu', ['attributesToHighlight' => ['overview']]);
index.search('shifu', {
attributesToHighlight: ['overview']
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
AttributesToHighlight: []string{"overview"},
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.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 will 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
}
}
When evaluated in HTML, the overview attribute in _formatted will look like as follows:
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.
Matches
This setting takes a Boolean value (true
or false
) and defines whether an object that contains information about the matches should be returned or not.
matches=<Boolean>
<Boolean>
(Optional, boolean, defaults tofalse
)If
true
, returns an array of the search query occurrences in all fields. A search query occurrence is given by astart
position in the field and thelength
of the occurrence.
TIP
This is useful when you need to highlight the results without the default HTML highlighter.
Example
If you set matches
to true
:
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "attributesToHighlight": ["overview"], "matches": true }'
client.index('movies').search('n', {
filters: 'title="Kung Fu Panda"',
attributesToHighlight: ['overview'],
matches: true
})
client.index('movies').search('n', {
'filters': 'title = "Kung Fu Panda"',
'attributesToHighlight': ['overview'],
'matches': 'true'
})
$client->index('movies')->search('shifu', ['attributesToHighlight' => ['overview'], 'matches' => true]);
index.search('n', {
filters: 'title="Kung Fu Panda"',
attributesToHighlight: ['overview'],
matches: true
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "n",
Filters: "title=\"Kung Fu Panda\"",
AttributesToHighlight: []string{"overview"},
Matches: true,
})
let results: SearchResults<Movie> = movies.search()
.with_query("n")
.with_filters(r#"title="Kung Fu Panda""#)
.with_attributes_to_highlight(Selectors::Some(&["overview"]))
.with_matches(true)
.execute()
.await
.unwrap();
// Get the matches info
let matched_info: Vec<&HashMap<String, Vec<MatchRange>>> = results.hits.iter().map(|r| r.matches_info.as_ref().unwrap()).collect();
You will get the following response with the 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
}
]
}
}
Examples
Here are a few examples of what can be achieved with search parameters:
Results can be paginated using the limit
and offset
query parameters.
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "shifu", "limit": 5, "offset": 10 }'
client.index('movies').search('shifu', {
limit: 5,
offset: 10
})
client.index('movies').search('shifu', {
'limit': 5,
'offset': 10
})
$client->index('movies')->search('shifu', ['limit' => 5, 'offset' => 10]);
index.search('shifu', {
limit: 5,
offset: 10
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "shifu",
Limit: 5,
Offset: 10,
})
let results: SearchResults<Movie> = movies.search()
.with_query("shifu")
.with_limit(5)
.with_offset(10)
.execute()
.await
.unwrap();
You can filter results using the filters
query parameter.
curl 'http://localhost:7700/indexes/movies/search' \
--data '{ "q": "Avengers", "filters": "release_date > 795484800" }'
client.index('movies').search('Avengers', {
filters: 'release_date > 795484800',
})
client.index('movies').search('Avengers', {
'filters': 'release_date > 795484800'
})
$client->index('movies')->search('Avengers', ['filters' => 'release_date > 795484800']);
index.search('Avengers', {
filters: 'release_date > 795484800'
})
results, error := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "Avengers",
Filters: "release_date > \"795484800\"",
})
let results: SearchResults<Movie> = movies.search()
.with_query("Avengers")
.with_filters("release_date > 795484800")
.execute()
.await
.unwrap();