Search parameters

Search parameters allow you greater control over the results returned by a MeiliSearch query.

WARNING

If using the GET route to perform a search, all parameters must be URL-encoded.

This is not necessary when using the POST route or one of our SDKs.

Parameters

Query ParameterDescriptionDefault Value
qSearch terms“”
offsetNumber of documents to skip0
limitMaximum number of documents returned20
filterFilter queries by an attribute’s valuenull
facetsDistributionDisplay the count of matches per facetnull
attributesToRetrieveAttributes to display in the returned documents[“*”]
attributesToCropAttributes whose values have to be croppednull
cropLengthMaximum field value length200
attributesToHighlightHighlight matching terms contained in an attributenull
matchesReturn matching terms locationfalse
sortSort search results by an attribute’s valuenull

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 fast search-as-you-type experience.

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. Since there is no query term, the built-in ranking rulesSearch parameters - 图1 (opens new window) do not apply.

If the index has no sort or custom ranking rules, the results are returned in the order of their internal database position.

TIP

Placeholder search is particularly useful when building a faceted search UI, as it allows users to view the catalog and alter sorting rules without entering a query.

Example

You can search for films mentioning shifu by setting the q parameter:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "shifu" }'
  1. client.index('movies').search('shifu')
  1. client.index('movies').search('shifu')
  1. $client->index('movies')->search('shifu');
  1. client.index("movies").search("shifu");
  1. client.index('movies').search('shifu')
  1. resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{})
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("shifu")
  3. .execute()
  4. .await
  5. .unwrap();
  1. client.index("movies").search(searchParameters(query: "shifu")) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  2. switch result {
  3. case .success(let searchResult):
  4. print(searchResult)
  5. case .failure(let error):
  6. print(error)
  7. }
  8. }
  1. await client.index('movies').search('shifu');

This will give you a list of documents that contain your query terms in at least one attribute.

  1. {
  2. "hits": [
  3. {
  4. "id": "50393",
  5. "title": "Kung Fu Panda Holiday",
  6. "poster": "https://image.tmdb.org/t/p/w500/rV77WxY35LuYLOuQvBeD1nyWMuI.jpg",
  7. "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.",
  8. "release_date": 1290729600,
  9. "genres": [
  10. "Animation",
  11. "Family",
  12. "TV Movie"
  13. ]
  14. }
  15. ],
  16. "query": "shifu"
  17. }

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 then proceed with its default behavior.

Example

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl -X POST 'http://localhost:7700/indexes/movies/search' \
  2. -H 'Content-Type: application/json' \
  3. --data-binary '{ "q": "\"african american\" horror" }'
  1. client.index('movies')
  2. .search('"african american" horror')
  1. client.index('movies').search('"african american" horror')
  1. $client->index('movies')->search('"african american" horror');
  1. client.index("movies").search("\"african american\" horror");
  1. client.index('movies').search('"african american" horror')
  1. resp, err := client.Index("movies").Search("\"african american\" horror", &meilisearch.SearchRequest{})
  1. let results: SearchResults<Movie> = movies
  2. .search()
  3. .with_query("\"african american\" horror")
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "\"african american\" horror")
  3. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  4. switch result {
  5. case .success(let searchResult):
  6. print(searchResult)
  7. case .failure(let error):
  8. print(error)
  9. }
  10. }
  1. await client.index('movies').search('"african american" horror');

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

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "shifu", "offset": 1 }'
  1. client.index('movies').search('shifu', {
  2. offset: 1
  3. })
  1. client.index('movies').search('shifu', {
  2. 'offset': 1
  3. })
  1. $client->index('movies')->search('shifu', ['offset' => 1]);
  1. SearchRequest searchRequest = new SearchRequest("shifu").setOffset(1);
  2. client.index("movies").search(searchRequest);
  1. client.index('movies').search('shifu', {
  2. offset: 1
  3. })
  1. resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
  2. Offset: 1,
  3. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("shifu")
  3. .with_offset(1)
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "shifu",
  3. offset: 1)
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('movies').search('shifu', offset: 1);

Limit

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.

Example

If you want your query to return only two documents, set limit to 2:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. - X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "shifu", "limit": 2 }'
  1. client.index('movies').search('shifu', {
  2. limit: 2
  3. })
  1. client.index('movies').search('shifu', {
  2. 'limit': 2
  3. })
  1. $client->index('movies')->search('shifu', ['limit' => 2]);
  1. SearchRequest searchRequest = new SearchRequest("shifu").setLimit(2);
  2. client.index("movies").search(searchRequest);
  1. client.index('movies').search('shifu', {
  2. limit: 2
  3. })
  1. resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
  2. Limit: 2,
  3. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("shifu")
  3. .with_limit(2)
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "shifu",
  3. limit: 2)
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('movies').search('shifu', limit: 2);

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.

Read our guide on filtering, faceted search and filter expressions.

Example

You can write a filter expression in string syntax using logical connectives:

  1. "(genres = horror OR genres = mystery) AND director = 'Jordan Peele'"

You can write the same filter as an array:

  1. [["genres = horror", "genres = mystery"], "director = 'Jordan Peele']

You can then use the filter in a search query:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "thriller", "filter": [["genres = Horror", "genres = Mystery"], "director = \"Jordan Peele\""] }'
  1. client.index('movies')
  2. .search('thriller', {
  3. filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
  4. })
  1. client.index('movies').search('thriller', {
  2. 'filter': [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
  3. })
  1. $client->index('movies')->search('thriller', ['filter' => [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("thriller").setFilterArray(new String[][] {
  3. new String[] {"genres = Horror", "genres = Mystery"},
  4. new String[] {"director = \"Jordan Peele\""}});
  5. client.index("movies").search(searchRequest);
  1. client.index('movies').search('thriller', {
  2. filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
  3. })
  1. resp, err := client.Index("movies").Search("thriller", &meilisearch.SearchRequest{
  2. Filter: [][]string{
  3. []string{"genres = Horror", "genres = Mystery"},
  4. []string{"director = \"Jordan Peele\""},
  5. },
  6. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("thriller")
  3. .with_filter("(genres = Horror AND genres = Mystery) OR director = \"Jordan Peele\"")
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "thriller",
  3. filter: [["genres = Horror", "genres = Mystery"], ["director = \"Jordan Peele\""]])
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('movies').search('thriller', filter: [
  2. ['genres = Horror', 'genres = Mystery'],
  3. 'director = "Jordan Peele"'
  4. ]);

Filtering results _geoRadius

If your documents contain _geo data, you can use the _geoRadius built-in filter rule to filter results according to their geographic position.

_geoRadius establishes a circular area based on a central point and a radius. Results beyond this area will be excluded from your search. This filter rule requires three parameters: lat, lng and distance_in_meters.

  1. _geoRadius(lat, lng, distance_in_meters)

lat and lng should be geographic coordinates expressed as floating point numbers. distance_in_meters indicates the radius of the area within which you want your results and should be an integer.

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl -X POST 'http://localhost:7700/indexes/restaurants/search' \
  2. -H 'Content-type:application/json' \
  3. --data-binary '{ "filter": "_geoRadius(45.4628328, 9.1076931, 2000)" }'
  1. client.index('restaurants').search('', {
  2. filter: ['_geoRadius(45.4628328, 9.1076931, 2000)'],
  3. })
  1. client.index('restaurants').search('', {
  2. 'filter': '_geoRadius(45.4628328, 9.1076931, 2000)'
  3. })
  1. $client->index('restaurants')->search('', ['filter' => '_geoRadius(45.4628328, 9.1076931, 2000)']);
  1. SearchRequest searchRequest =
  2. new SearchRequest("").setFilter(new String[] {"_geoRadius(45.4628328, 9.1076931, 2000)"});
  3. client.index("restaurants").search(searchRequest);
  1. client.index('restaurants').search('', { filter: '_geoRadius(45.4628328, 9.1076931, 2000)' })
  1. resp, err := client.Index("restaurants").Search("", &meilisearch.SearchRequest{
  2. Filter: "_geoRadius(45.4628328, 9.1076931, 2000)",
  3. })
  1. let results: SearchResults<Restaurant> = restaurants.search()
  2. .with_filter("_geoRadius(45.4628328, 9.1076931, 2000)")
  3. .execute()
  4. .await
  5. .unwrap();
  1. let searchParameters = SearchParameters(
  2. filter: ["_geoRadius(45.4628328, 9.1076931, 2000)"]
  3. )
  4. client.index("restaurants").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await await client
  2. .index('restaurants')
  3. .search('', filter: '_geoRadius(45.4628328, 9.1076931, 2000)');

Facets distribution

Parameter: facetsDistribution
Expected value: an array of attributes 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 facet
  • exhaustiveFacetsCount: A true or false 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 facetNames. 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.

Learn more about facet distribution in the filtering and faceted search guide.

Example

Given a movie database, suppose that you want to know the number of Batman movies per genre:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "Batman", "facetsDistribution": ["genres"] }'
  1. client.index('movies')
  2. .search('Batman', {
  3. facetsDistribution: ['genres']
  4. })
  1. client.index('movies').search('Batman', {
  2. 'facetsDistribution': ['genres']
  3. })
  1. $client->index('movies')->search('Batman', ['facetsDistribution' => ['genres']]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("Batman").setFacetsDistribution(new String[] {"genres"});
  3. client.index("movies").search(searchRequest);
  1. client.index('movies').search('Batman', {
  2. facets_distribution: ['genres']
  3. })
  1. resp, err := client.Index("movies").Search("Batman", &meilisearch.SearchRequest{
  2. FacetsDistribution: []string{
  3. "genres",
  4. },
  5. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("Batman")
  3. .with_facets_distribution(Selectors::Some(&["genres"]))
  4. .execute()
  5. .await
  6. .unwrap();
  7. let genres: &HashMap<String, usize> = results.facets_distribution.unwrap().get("genres").unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "Batman",
  3. facetsDistribution: ["genres"]])
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('movies').search('Batman', facetsDistribution: ['genres']);

You would get the following response:

  1. {
  2. "nbHits": 1684,
  3. "query": "Batman",
  4. "exhaustiveFacetsCount": false,
  5. "facetsDistribution": {
  6. "genres": {
  7. "action": 273,
  8. "animation": 118,
  9. "adventure": 132,
  10. "fantasy": 67,
  11. "comedy": 475,
  12. "mystery": 70,
  13. "thriller": 217
  14. }
  15. }
  16. }

Attributes to retrieve

Parameter: attributesToRetrieve
Expected value: an array of attributes or ["*"]
Default value: ["*"]

Configures which attributes will be retrieved in the returned documents.

If no value is specified, attributesToRetrieve uses the displayedAttributes list, which by default contains all attributes found in the documents.

Example

To get only the overview and title fields, set attributesToRetrieve to ["overview", "title"].

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "shifu", "attributesToRetrieve": ["overview", "title"] }'
  1. client.index('movies').search('shifu', {
  2. attributesToRetrieve: ['overview', 'title']
  3. })
  1. client.index('movies').search('shifu', {
  2. 'attributesToRetrieve': ['overview', 'title']
  3. })
  1. $client->index('movies')->search('shifu', ['attributesToRetrieve' => ['overview', 'title']]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("a").setAttributesToRetrieve(new String[] {"overview", "title"});
  3. client.index("movies").search(searchRequest);
  1. client.index('movies').search('shifu', {
  2. attributes_to_retrieve: ['overview', 'title']
  3. })
  1. resp, err := client.Index("movies").Search("shifu", &meilisearch.SearchRequest{
  2. AttributesToRetrieve: []string{"overview", "title"},
  3. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("shifu")
  3. .with_attributes_to_retrieve(Selectors::Some(&["overview", "title"]))
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "shifu",
  3. attributesToRetrieve: ["overview", "title"])
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client
  2. .index('movies')
  3. .search('shifu', attributesToRetrieve: ['overview', 'title']);

Attributes to crop

Parameter: attributesToCrop
Expected value: an array of attribute or ["*"]
Default value: null

Crops the selected attributes’ values in the returned results to the length indicated by the cropLength 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

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "shifu", "attributesToCrop": ["overview"], "cropLength": 10 }'
  1. client.index('movies').search('shifu', {
  2. attributesToCrop: ['overview'],
  3. cropLength: 10
  4. })
  1. client.index('movies').search('shifu', {
  2. 'attributesToCrop': ['overview'],
  3. 'cropLength': 10
  4. })
  1. $client->index('movies')->search('shifu', ['attributesToCrop' => ['overview'], 'cropLength' => 10]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("shifu")
  3. .setAttributesToCrop(new String[] {"overview"})
  4. .setCropLength(10);
  5. client.index("movies").search(searchRequest);
  1. client.index('movies').search('shifu', {
  2. attributes_to_crop: ['overview'],
  3. cropLength: 10
  4. })
  1. resp, err := client.Index("movies").Search("shifu" &meilisearch.SearchRequest{
  2. AttributesToCrop: []string{"overview"},
  3. CropLength: 10,
  4. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("shifu")
  3. .with_attributes_to_crop(Selectors::Some(&[("overview", None)]))
  4. .with_crop_length(10)
  5. .execute()
  6. .await
  7. .unwrap();
  8. // Get the formatted results
  9. let formatted_results: Vec<&Movie> = results.hits.iter().map(|r| r.formatted_result.as_ref().unwrap()).collect();
  1. let searchParameters = SearchParameters(
  2. query: "shifu",
  3. attributesToCrop: "overview",
  4. cropLength: 10)
  5. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  6. switch result {
  7. case .success(let searchResult):
  8. print(searchResult)
  9. case .failure(let error):
  10. print(error)
  11. }
  12. }
  1. await client
  2. .index('movies')
  3. .search('shifu', attributesToCrop: ['overview'], cropLength: 10);

You will get the following response with the cropped text in the _formatted object:

  1. {
  2. "id": "50393",
  3. "title": "Kung Fu Panda Holiday",
  4. "poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
  5. "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.",
  6. "release_date": 1290729600,
  7. "_formatted": {
  8. "id": "50393",
  9. "title": "Kung Fu Panda Holiday",
  10. "poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
  11. "overview": "this year Shifu informs",
  12. "release_date": 1290729600
  13. }
  14. }

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 attributesToCrop 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.

Attributes to highlight

Parameter: attributesToHighlight
Expected value: an array of attributes 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

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "winter feast", "attributesToHighlight": ["overview"] }'
  1. client.index('movies').search('winter feast', {
  2. attributesToHighlight: ['overview']
  3. })
  1. client.index('movies').search('winter feast', {
  2. 'attributesToHighlight': ['overview']
  3. })
  1. $client->index('movies')->search('winter feast', ['attributesToHighlight' => ['overview']]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("and").setAttributesToHighlight(new String[] {"overview"});
  3. client.index("movies").search(searchRequest);
  1. client.index('movies').search('winter feast', {
  2. attributes_to_highlight: ['overview']
  3. })
  1. resp, err := client.Index("movies").Search("winter feast", &meilisearch.SearchRequest{
  2. AttributesToHighlight: []string{"overview"},
  3. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("winter feast")
  3. .with_attributes_to_highlight(Selectors::Some(&["overview"]))
  4. .execute()
  5. .await
  6. .unwrap();
  7. // Get the formatted results
  8. let formatted_results: Vec<&Movie> = results.hits.iter().map(|r| r.formatted_result.as_ref().unwrap()).collect();
  1. let searchParameters = SearchParameters(
  2. query: "winter feast",
  3. attributesToHighlight: ["overview"])
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client
  2. .index('movies')
  3. .search('winter feast', attributesToHighlight: ['overview']);

You would get the following response with the highlighted version in the _formatted object:

  1. {
  2. "id": "50393",
  3. "title": "Kung Fu Panda Holiday",
  4. "poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
  5. "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.",
  6. "release_date": 1290729600,
  7. "_formatted": {
  8. "id": "50393",
  9. "title": "Kung Fu Panda Holiday",
  10. "poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
  11. "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.",
  12. "release_date": 1290729600
  13. }
  14. }

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 built-in highlighting.

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.

matches does not work with array or object values—only strings.

Example

If you set matches to true and search for shifu:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/movies/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{ "q": "winter feast", "matches": true }'
  1. client.index('movies').search('winter feast', {
  2. matches: true
  3. })
  1. client.index('movies').search('winter feast', {
  2. 'matches': 'true'
  3. })
  1. $client->index('movies')->search('winter feast', ['attributesToHighlight' => ['overview'], 'matches' => true]);
  1. SearchRequest searchRequest = new SearchRequest("winter feast").setMatches(true);
  2. SearchResult searchResult = index.search(searchRequest);
  1. client.index('movies').search('winter feast', {
  2. matches: true
  3. })
  1. resp, err := client.Index("movies").Search("winter feast", &meilisearch.SearchRequest{
  2. Matches: true,
  3. })
  1. let results: SearchResults<Movie> = movies.search()
  2. .with_query("winter feast")
  3. .with_matches(true)
  4. .execute()
  5. .await
  6. .unwrap();
  7. // Get the matches info
  8. let matched_info: Vec<&HashMap<String, Vec<MatchRange>>> = results.hits.iter().map(|r| r.matches_info.as_ref().unwrap()).collect();
  1. let searchParameters = SearchParameters(
  2. query: "winter feast",
  3. matches: true)
  4. client.index("movies").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('movies').search('winter feast', matches: true);

You would get the following response with information about the matches in the _matchesInfo object:

  1. {
  2. "id": "50393",
  3. "title": "Kung Fu Panda Holiday",
  4. "poster": "https://image.tmdb.org/t/p/w1280/gp18R42TbSUlw9VnXFqyecm52lq.jpg",
  5. "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.",
  6. "release_date": 1290729600,
  7. "_matchesInfo": {
  8. "overview": [
  9. {
  10. "start": 159,
  11. "length": 5
  12. },
  13. {
  14. "start": 361,
  15. "length": 5
  16. }
  17. ]
  18. }
  19. }

Sort

Parameter: sort
Expected value: a list of attributes written as an array or as a comma-separated string
Default value: null

Sorts search results at query time according to the specified attributes and indicated order.

Each attribute in the list must be followed by a colon (:) and the preferred sorting order: either ascending (asc) or descending (desc).

NOTE

Attribute order is meaningful. The first attributes in a list will be given precedence over those that come later.

For example, sort="price:asc,author:desc will prioritize price over author when sorting results.

When using the POST route, sort expects an array of strings.

When using the GET route, sort expects the list as a comma-separated string.

Read more about sorting search results in our dedicated guide.

Example

You can search for science fiction books ordered from cheapest to most expensive:

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl \
  2. -X POST 'http://localhost:7700/indexes/books/search' \
  3. -H 'Content-Type: application/json' \
  4. --data-binary '{
  5. "q": "science fiction",
  6. "sort": [
  7. "price:asc"
  8. ]
  9. }'
  1. client.index('books').search('science fiction', {
  2. sort: ['price:asc'],
  3. })
  1. client.index('books').search('science fiction', {
  2. 'sort': ['price:asc']
  3. })
  1. $client->index('books')->search('science fiction', ['sort' => ['price:asc']]);
  1. SearchRequest searchRequest = new SearchRequest("science fiction").setSort(new String[] {"price:asc"});
  2. client.index("search_parameter_guide_sort_1").search(searchRequest);
  1. client.index('books').search('science fiction', { sort: ['price:asc'] })
  1. resp, err := client.Index("books").Search("science fiction", &meilisearch.SearchRequest{
  2. Sort: []string{
  3. "price:asc",
  4. },
  5. })
  1. let results: SearchResults<Books> = books.search()
  2. .with_query("science fiction")
  3. .with_sort(&["price:asc"])
  4. .execute()
  5. .await
  6. .unwrap();
  1. let searchParameters = SearchParameters(
  2. query: "science fiction",
  3. sort: ["price:asc"]
  4. )
  5. client.index("books").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  6. switch result {
  7. case .success(let searchResult):
  8. print(searchResult)
  9. case .failure(let error):
  10. print(error)
  11. }
  12. }
  1. await client.index('books').search('science fiction', sort: ['price:asc']);

Sorting results with _geoPoint

When dealing with documents containing geolocation data, you can use _geoPoint to sort results based on their distance from a specific geographic location.

_geoPoint is a sorting function that requires two floating point numbers indicating a location’s latitude and longitude. You must also specify whether the sort should be ascending (asc) or descending (desc):

<>

cURL

JS

Python

PHP

Java

Ruby

Go

Rust

Swift

Dart

  1. curl -X POST 'http://localhost:7700/indexes/restaurants/search' \
  2. -H 'Content-type:application/json' \
  3. --data-binary '{ "sort": ["_geoPoint(48.8583701,2.2922926):asc"] }'
  1. client.index('restaurants').search('', {
  2. sort: ['_geoPoint(48.8583701,2.2922926):asc'],
  3. })
  1. client.index('restaurants').search('', {
  2. 'sort': ['_geoPoint(48.8583701,2.2922926):asc']
  3. })
  1. $client->index('restaurants')->search('', ['sort' => ['_geoPoint(48.8583701,2.2922926):asc']]);
  1. SearchRequest searchRequest =
  2. new SearchRequest("").setSort(new String[] {"_geoPoint(48.8583701,2.2922926):asc"});
  3. client.index("restaurants").search(searchRequest);
  1. client.index('restaurants').search('', { sort: ['_geoPoint(48.8583701,2.2922926):asc'] })
  1. resp, err := client.Index("restaurants").Search("", &meilisearch.SearchRequest{
  2. Sort: []string{
  3. "_geoPoint(48.8583701,2.2922926):asc",
  4. },
  5. })
  1. let results: SearchResults<Restaurant> = restaurants.search()
  2. .with_sort(&["_geoPoint(48.8583701,2.2922926):asc"])
  3. .execute()
  4. .await
  5. .unwrap();
  1. let searchParameters = SearchParameters(
  2. sort: ["_geoPoint(48.8583701,2.2922926):asc"]
  3. )
  4. client.index("restaurants").search(searchParameters) { (result: Result<SearchResult<Movie>, Swift.Error>) in
  5. switch result {
  6. case .success(let searchResult):
  7. print(searchResult)
  8. case .failure(let error):
  9. print(error)
  10. }
  11. }
  1. await client.index('restaurants').search('', sort: ['_geoPoint(48.8583701,2.2922926):asc']);

Queries using _geoPoint will always include a geoDistance field containing the distance in meters between the document location and the _geoPoint:

  1. [
  2. {
  3. "id": 1,
  4. "name": "Nàpiz' Milano",
  5. "_geo": {
  6. "lat": 45.4777599,
  7. "lng": 9.1967508
  8. },
  9. "_geoDistance": 1532
  10. }
  11. ]

You can read more about location-based sorting in our dedicated guide.