Meilisearch 1.10
Today we're announcing Meilisearch v1.10. In this article, we’ll review the most impactful changes. For an exhaustive listing, check out the changelog on GitHub.
New: federated search
We’re excited to announce that federated search is finally coming to Meilisearch. This feature extends the multi-search API to allow you to merge results from multiple queries into a single, unified response. You can now search different indexes and get the most relevant results across the entire dataset, not only the most relevant for each index.
For SaaS platforms that need to search across various types of resources or ecommerce sites with diverse product categories, federated search is a game-changer.
Here is an example payload for making a federated search request against the movies
and comics
indexes:
{
"federation": {
"offset": 5,
"limit": 10
},
"queries": [
{
"q": "Batman",
"indexUid": "movies"
},
{
"q": "Batman",
"indexUid": "comics"
}
]
}
In this example, the federated search response will look like this:
{
"hits": [
{
"id": 42,
"title": "Batman returns",
"overview": "..",
"_federation": {
"indexUid": "movies",
"queriesPosition": 0
}
},
{
"comicsId": "batman-killing-joke",
"description": "..",
"title": "Batman: the killing joke",
"_federation": {
"indexUid": "comics",
"queriesPosition": 1
}
},
],
"processingTimeMs": 0,
"limit": 2,
"offset": 0,
"estimatedTotalHits": 2,
"semanticHitCount": 0
}
Query weighting
Federated search isn't just about combining results; it's about making those results more meaningful and relevant. Thanks to query weighting, you can prioritize certain queries over others, ensuring that the most important data rises to the top.
The example payload below uses query weighting in a federated search to give more importance to documents where the boosted
field is true
:
{
"federation": {},
"queries": [
{
"q": "iphone case",
"indexUid": "products",
"filter": "BOOSTED = true",
"federationOptions": {
"weight": 3.0
}
},
{
"q": "iphone case",
"indexUid": "products"
// federationOptions.weight defaults to 1
}
]
}
New: language settings for queries and documents
By default, Meilisearch automatically detects the language used in documents and queries. This comes with some limitations for edge cases. Meilisearch 1.10 introduces new language settings that allow users to manually customize their language preferences.
There are two ways to state the language used in a search:
- Set the language used in a query
- Set the language used in a document field
Setting the search query locale
You can define which language is used in a query in the search parameters.
Example payload for searching with query locales
:
{
"q": "進撃の巨人",
"locales": ["jpn"]
}
Setting the document attributes’ locales
You can define which language is used in your dataset via the index settings.
Example payload for settings with localizedAttributes
:
{
"localizedAttributes": [
{
"locales": ["jpn"],
"attributePatterns": ["*_japanese"]
}
]
}
Self-hosting: Ubuntu v20 is now required
If you’re self-hosting Meilisearch, take note: Meilisearch 1.10 now requires Ubuntu version 20. This update ensures compatibility with the latest features and maintains optimal performance and security. We advise reading the documentation on how to upgrade your Ubuntu release.
Experimental: AI-powered search DX improvements
New: custom headers to REST API-based embedders
Meilisearch 1.10 supports sending custom headers to your API-based embedding service. When using the rest
source for your embedder settings, Meilisearch now accepts an optional headers
object. These headers will be added to all requests made to the embedder API.
Example payload for embedder settings:
{
"source": "rest",
"apiKey": "•••••••••••••••••",
"headers": {
"Custom-Header": "value"
}
}
New: quality of life improvements
Additionally, we added some minor changes to make working with Meilisearch AI-powered search API easier:
- Embedder settings now accept a
url
parameter for OpenAI embedder to access OpenAI through a proxy - Embedder settings now accept a
dimensions
parameter for ollama embedder - Meilisearch now includes
_vectors
in the response for documents without vectors (only whenretrieveVectors
is enabled)
⚠️ Breaking: REST API-based embedders breaking changes
The API for configuring an embedder based on a REST API (e.g., OpenAI, Mistral, etc.) has quickly evolved and to avoid confusion, we have decided to reorganize the parameters in dedicated request
and response
fields.
In practice, this change:
- removes
query
,inputField
,inputType
,pathToEmbeddings
andembeddingObject
fields - adds
request
andresponse
fields
Take a look at the example below to learn how to migrate to the new syntax.
Before — With Meilisearch 1.9
{
"source": "rest",
"url": "https://localhost:10006",
"query": {
"model": "minillm",
},
"inputField": ["prompt"],
"inputType": "text",
"embeddingObject": ["embedding"]
}
After — Starting with Meilisearch 1.10
{
"source": "rest",
"url": "https://localhost:10006",
"request": {
"model": "minillm",
"prompt": "{{text}}"
},
"response": {
"embedding": "{{embedding}}"
}
}
Upgrade procedure
This procedure is only necessary if you're using REST API-based embedder. To upgrade to Meilisearch 1.10, follow these steps:
- Remove embedders with source
"rest"
- Update your Meilisearch Cloud project or self-hosted Meilisearch instance as usual
Experimental: CONTAINS
filter operator
Meilisearch 1.10 introduces the CONTAINS
operator. This is still in the experimental stage due to some performance issues we’re working to resolve. This new filter operator allows to check if a substring is included in a larger string.
Given the document { id: 1, name: "Keffir" }
, you can use the filter as follows:
name CONTAINS kef
— search will match the documentname CONTAINS clifford
— search will not match the document
Experimental: update documents with a function
Meilisearch 1.10 allows you to edit documents by executing a Rhai function. This allows you to update only a part of your dataset using filters. Additionally, using a function allows you to implement dynamic logic based on your documents’ data.
The following payload updates the title of all documents with id
above 3000:
{
"filter": "id > 3000",
"function": "doc.title = `✨ ${doc.title.to_upper()} ✨`"
}
This also enables more complex use cases, like implementing a decaying ranking strategy. Depending on your needs, you might implement a function such as the following that will be run regularly by a Cron job.
{
"context": { "now": 1715423249 },
"function": "
// `posted_at` and `now` are Unix Epoch timestamps in seconds
// they must be converted to hours.
let age_hours = (context.now - doc.posted_at) / 60 / 60;
doc.ranking_score = doc.upvotes ** 0.8 / (age_hours + 2) ** 1.8;
"
}
And that’s a wrap for v1.10! These release notes only highlights the most significant updates. For an exhaustive listing, read the changelog on Github.
Upgrade with ease using Meilisearch Cloud.
Contributors shout-out
This release wouldn’t be possible without Meilisearch and Charabia contributors @Karribalu, @hanbings, @junhochoi, @JWSong, @PeterDaveHello, @LukasKalbertodt, and @phillitrOSU.
We also want to extend special thanks to our SDK maintainers working hard to make Meilisearch available across many languages and frameworks. We’re excited for @Sherlouk and @Ja7ad to join our open-source maintainers. 💪
Stay in the loop of everything Meilisearch by subscribing to our monthly newsletter. To learn more about Meilisearch's future and help shape it, take a look at our roadmap and participate in our Product Discussions.
For anything else, join our developers community on Discord.