发布日期: 2026-04-13
版本号: v1.42.0

Meilisearch在最新版本中推出了多项功能改进与问题修复。主要增强包括:在企业版的分片与复制功能中,新增了远程节点不可用时的搜索回退机制,系统能够自动检测并避开离线节点,待其恢复后重新启用。同时,引入了实验性的跨索引文档关联过滤功能(需启用foreignKeys特性),允许在搜索时通过_foreign过滤器对关联的外部索引文档进行条件筛选,从而实现更灵活的跨索引数据关联查询,但此功能暂不支持远程分片环境。

在错误修复方面,解决了网络拓扑变更时的竞争条件问题,确保文档正确索引;修正了更新模板设置时未能正确提示文档模板错误的问题;并确保了更新索引的任务能够正确转发至远程节点,以及修复了聊天补全路由中的操作错误。

此外,本次更新还将底层依赖升级至最新的heed版本(v0.22.1),以获得稳定的嵌套读事务支持,同时进行了多项文档维护、安全加固及代码清理工作。

更新内容 (中文)

✨ 增强功能

支持远程不可用时的搜索回退

由 @Kerollmops 在 https://github.com/meilisearch/meilisearch/pull/6306 提交

我们为分片和复制企业版功能引入了一个新的回退系统,以及一种确定远程实例可用性的方法。引擎可以避开一段时间内不可用的机器,并在它们恢复在线后重新查询它们。

以下代码片段展示了此 PR 暴露远程状态/可用性后,/network 路由现在的样子。

"remotes": {
    "prod2": {
      "url": "http://localhost:7702",
      "searchApiKey": "mykey",
      "writeApiKey": "mykey",
      "status": "available"
    },
    "prod3": {
      "url": "http://localhost:7703",
      "searchApiKey": "mykey",
      "writeApiKey": "mykey",
      "status": "unavailable"
    }
}

🔬 实验性功能:文档联接过滤

由 @ManyTheFish 在 https://github.com/meilisearch/meilisearch/pull/6314 提交

此增强功能扩展了在 v1.39.0 中引入的 跨索引文档水合 功能,允许用户在外部索引上进行过滤以检索文档。

📓 注意:此实现不支持远程分片环境

foreignKeys 实验性功能

必须激活 foreignKeys 实验性功能才能使用外部过滤器:

curl -X PATCH 'http://127.0.0.1:7700/experimental-features' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": true}'

foreignKeys + filter 索引设置

要能使用外部过滤器,相关字段必须在 /indexes/{index_uid}/settings 中同时设置为 foreignKeyfilterableAttribute

{
	// 新设置,一个允许索引之间存在多个外部关系的外部键数组
	"foreignKeys":  [
		{
			// JSON 文档中包含外部文档 ID 的路径
			"fieldName": "actors",
			
			// 包含在水合期间要获取的文档的外部索引的 UID
	        "foreignIndexUid": "actors"
		}
	],
	// actors 字段必须支持基于等式的过滤
	"filterableAttributes": [
		{
	    	"attributePatterns": ["actors"],
	     	"features": {
				"facetSearch": false,
				"filter": {
					"equality": true,
					"comparison": false
				}
			}
		}
	]
}

使用 _foreign 过滤器进行过滤

在搜索路由上,引入了一个新的 _foreign 动词,应按如下方式使用:

{
	"q": "<查询内容>",

	// 在电影索引上过滤:
	// 类型 = 动作
    // 并且
    // 来自演员索引的外部文档匹配:出生日期以 "1958-" 开头 且 人气 >= 3.5
	"filter": "genres = action AND _foreign(actors, birthday STARTS WITH \"1958-\" AND popularity >= 3.5)"
}

注意:不支持嵌套外部过滤器,将会返回错误。

使用示例

先决条件

  • Meilisearch 在 document-join-hydration 分支上运行于 127.0.0.1:7700

步骤 1:启用 Foreign Keys 功能

curl -X PATCH 'http://127.0.0.1:7700/experimental-features' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": true}'

步骤 2:创建索引

创建 actors 索引
curl -X POST 'http://127.0.0.1:7700/indexes' \
  -H 'Content-Type: application/json' \
  --data-binary '{"uid": "actors", "primaryKey": "id"}'
创建 movies 索引
curl -X POST 'http://127.0.0.1:7700/indexes' \
  -H 'Content-Type: application/json' \
  --data-binary '{"uid": "movies", "primaryKey": "id"}'

步骤 3:向 actors 索引添加文档

curl -X POST 'http://127.0.0.1:7700/indexes/actors/documents' \
  -H 'Content-Type: application/json' \
  --data-binary '[
  {"id": 1, "name": "Tom", "familyName": "Hanks", "birthDate": "1956-07-09"},
  {"id": 2, "name": "Meryl", "familyName": "Streep", "birthDate": "1949-06-22"},
  {"id": 3, "name": "Leonardo", "familyName": "DiCaprio", "birthDate": "1974-11-11"},
  {"id": 4, "name": "Emma", "familyName": "Watson", "birthDate": "1990-04-15"}
]'

步骤 4:向 movies 索引添加文档

curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' \
  -H 'Content-Type: application/json' \
  --data-binary '[
  {"id": 1, "title": "Forrest Gump", "description": "The presidencies of Kennedy and Johnson, the Vietnam War, the Watergate scandal and other historical events unfold from the perspective of an Alabama man with an IQ of 75.", "actors": [1]},
  {"id": 2, "title": "The Devil Wears Prada", "description": "A smart but sensible new graduate lands a job as an assistant to Miranda Priestly, the demanding editor-in-chief of a high fashion magazine.", "actors": [2, 4]},
  {"id": 3, "title": "Inception", "description": "A thief who steals corporate secrets through the use of dream-sharing technology is given the inverse task of planting an idea into the mind of a C.E.O.", "actors": [3]},
  {"id": 4, "title": "Cast Away", "description": "A FedEx executive undergoes a physical and emotional transformation after crash landing on a deserted island.", "actors": [1]}
]'

步骤 5:在 movies 索引上配置 Foreign Keys

curl -X PATCH 'http://127.0.0.1:7700/indexes/movies/settings' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": [{"fieldName": "actors", "foreignIndexUid": "actors"}], "filterableAttributes": [{"attributePatterns": ["actors"],"features": {"facetSearch": false,"filter": {"equality": true,"comparison": false}}}]}'

步骤 6:在 actors 索引上配置可过滤属性

curl -X PATCH 'http://127.0.0.1:7700/indexes/actors/settings' \
  -H 'Content-Type: application/json' \
  --data-binary '{"filterableAttributes": [{"attributePatterns": ["birthDate"],"features": {"facetSearch": false,"filter": {"equality": true,"comparison": false}}}]}'

步骤 7:执行联合搜索

curl -X POST 'http://127.0.0.1:7700/multi-search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
  "queries": [
    {
      "indexUid": "movies",
      "q": "Forrest",
      "filter": "_foreign(actors, birthDate = \"1956-07-09\")"
    }
  ],
  "federation": {
    "limit": 20,
    "offset": 0
  }
}'

预期结果

联合搜索应返回电影文档,其中 actors 数组已自动用水合后的完整演员对象填充,而不仅仅是 ID:

{
  "hits": [
    {
      "id": 1,
      "title": "Forrest Gump",
      "description": "...",
      "actors": [
        {
          "id": 1,
          "name": "Tom",
          "familyName": "Hanks",
          "birthDate": "1956-07-09"
        }
      ],
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 0,
        "weightedRankingScore": 0.9848484848484849
      }
    }
  ],
  "processingTimeMs": 208,
  "limit": 20,
  "offset": 0,
  "estimatedTotalHits": 1
}

🪲 错误修复

  • 修复写入网络时的竞态条件,由 @Kerollmops 在 https://github.com/meilisearch/meilisearch/pull/6300 提交

    我们修复了网络拓扑变更中的一个竞态条件,该条件可能导致错误并阻止文档被正确索引。此外,我们修复了 networkTopologyChange 任务批处理中的一个错误,该错误导致其批处理了过多的任务类型。我们确保它只批处理导入任务,并且仅批处理这些任务,以避免任务处理顺序错乱。

  • 更新聊天设置时抛出文档模板错误,由 @Kerollmops 在 https://github.com/meilisearch/meilisearch/pull/6321 提交

    我们修复了一个问题,该问题阻止引擎在用户更新模板时明确显示可能遇到的文档模板错误。引擎现在正确检查并在检测到模板错误时抛出它们。

  • 修复:更新索引任务将被正确转发到远程节点,由 @dureuill 在 https://github.com/meilisearch/meilisearch/pull/6299 提交

  • 修复聊天补全路由上的操作错误,由 @Kerollmops 在 https://github.com/meilisearch/meilisearch/pull/6290 提交

🔩 其他事项

更新内容 (原始)

✨ Enhancement

Support search fallback on remote unavailability

By @Kerollmops in https://github.com/meilisearch/meilisearch/pull/6306

We introduce a new fallback system for the sharding and replication enterprise edition feature, along with a way to determine which remote is available. The engine can avoid machines that are unavailable for a period and resume querying them once they’re back online.

The following snippet shows what the /network route looks like now that this PR exposes the remote statuses/availabilities.

"remotes": {
	"prod2": {
	  "url": "http://localhost:7702",
	  "searchApiKey": "mykey",
	  "writeApiKey": "mykey",
	  "status": "available"
	},
	"prod3": {
	  "url": "http://localhost:7703",
	  "searchApiKey": "mykey",
	  "writeApiKey": "mykey",
	  "status": "unavailable"
	}
}

🔬 Experimental: Document join Filtering

By @ManyTheFish in https://github.com/meilisearch/meilisearch/pull/6314

This enhancement extends the Cross-index document hydration introduced in v1.39.0 by allowing the user to filter on the foreign indexes to retrieve the documents.

📓 Note: This implementation doesn’t support a remote sharding environment

foreignKeys experimental feature

TheforeignKeys experimental feature must be activated to use the foreign filters:

curl -X PATCH 'http://127.0.0.1:7700/experimental-features' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": true}'

foreignKeys + filter index setting

To be able to use the foreign filters, the related field must be set as a foreignKey and as a filterableAttribute in /indexes/{index_uid}/settings:

{
	// new setting, an array of foreign keys that allows multiple foreign relationships between indexes
	"foreignKeys":  [
		{
			// the path in the JSON document containing foreign document ids
			"fieldName": "actors",
			
			// the UID of the foreign index containing the documents to fetch during hydration
	        "foreignIndexUid": "actors"
		}
	],
	// the actors field must be filterable on equality
	"filterableAttributes": [
		{
	    	"attributePatterns": ["actors"],
	     	"features": {
				"facetSearch": false,
				"filter": {
					"equality": true,
					"comparison": false
				}
			}
		}
	]
}

filtering using the _foreign filter

On the search route, a new _foreign verb has been introduced and should be used as follows:

{
	"q": "<query>",

	// filters on the movie index:
	// genres = action
    // AND
    // the foreign documents from the actor index match:  birthday STARTS WITH \"1958-\" AND popularity >= 3.5
	"filter": "genres = action AND _foreign(actors, birthday STARTS WITH \"1958-\" AND popularity >= 3.5)"
}

Note: nesting foreign filters is not supported and will return an error

Example of usage

Prerequisites

  • Meilisearch running on 127.0.0.1:7700 on the document-join-hydration branch.

Step 1: Enable Foreign Keys Feature

curl -X PATCH 'http://127.0.0.1:7700/experimental-features' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": true}'

Step 2: Create Indexes

Create the actors index
curl -X POST 'http://127.0.0.1:7700/indexes' \
  -H 'Content-Type: application/json' \
  --data-binary '{"uid": "actors", "primaryKey": "id"}'
Create the movies index
curl -X POST 'http://127.0.0.1:7700/indexes' \
  -H 'Content-Type: application/json' \
  --data-binary '{"uid": "movies", "primaryKey": "id"}'

Step 3: Add Documents to the actors Index

curl -X POST 'http://127.0.0.1:7700/indexes/actors/documents' \
  -H 'Content-Type: application/json' \
  --data-binary '[
  {"id": 1, "name": "Tom", "familyName": "Hanks", "birthDate": "1956-07-09"},
  {"id": 2, "name": "Meryl", "familyName": "Streep", "birthDate": "1949-06-22"},
  {"id": 3, "name": "Leonardo", "familyName": "DiCaprio", "birthDate": "1974-11-11"},
  {"id": 4, "name": "Emma", "familyName": "Watson", "birthDate": "1990-04-15"}
]'

Step 4: Add Documents to the movies Index

curl -X POST 'http://127.0.0.1:7700/indexes/movies/documents' \
  -H 'Content-Type: application/json' \
  --data-binary '[
  {"id": 1, "title": "Forrest Gump", "description": "The presidencies of Kennedy and Johnson, the Vietnam War, the Watergate scandal and other historical events unfold from the perspective of an Alabama man with an IQ of 75.", "actors": [1]},
  {"id": 2, "title": "The Devil Wears Prada", "description": "A smart but sensible new graduate lands a job as an assistant to Miranda Priestly, the demanding editor-in-chief of a high fashion magazine.", "actors": [2, 4]},
  {"id": 3, "title": "Inception", "description": "A thief who steals corporate secrets through the use of dream-sharing technology is given the inverse task of planting an idea into the mind of a C.E.O.", "actors": [3]},
  {"id": 4, "title": "Cast Away", "description": "A FedEx executive undergoes a physical and emotional transformation after crash landing on a deserted island.", "actors": [1]}
]'

Step 5: Configure Foreign Keys on the movies Index

curl -X PATCH 'http://127.0.0.1:7700/indexes/movies/settings' \
  -H 'Content-Type: application/json' \
  --data-binary '{"foreignKeys": [{"fieldName": "actors", "foreignIndexUid": "actors"}], "filterableAttributes": [{"attributePatterns": ["actors"],"features": {"facetSearch": false,"filter": {"equality": true,"comparison": false}}}]}'

Step 6: Configure filterable on the actors Index

curl -X PATCH 'http://127.0.0.1:7700/indexes/actors/settings' \
  -H 'Content-Type: application/json' \
  --data-binary '{"filterableAttributes": [{"attributePatterns": ["birthDate"],"features": {"facetSearch": false,"filter": {"equality": true,"comparison": false}}}]}'
curl -X POST 'http://127.0.0.1:7700/multi-search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
  "queries": [
    {
      "indexUid": "movies",
      "q": "Forrest",
      "filter": "_foreign(actors, birthDate = \"1956-07-09\")"
    }
  ],
  "federation": {
    "limit": 20,
    "offset": 0
  }
}'

Expected Result

The federated search should return movie documents with the actors array automatically hydrated with full actor objects instead of just IDs:

{
  "hits": [
    {
      "id": 1,
      "title": "Forrest Gump",
      "description": "...",
      "actors": [
        {
          "id": 1,
          "name": "Tom",
          "familyName": "Hanks",
          "birthDate": "1956-07-09"
        }
      ],
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 0,
        "weightedRankingScore": 0.9848484848484849
      }
    }
  ],
  "processingTimeMs": 208,
  "limit": 20,
  "offset": 0,
  "estimatedTotalHits": 1
}

🪲 Bug fixes

  • Fix a race condition when writing network by @Kerollmops in https://github.com/meilisearch/meilisearch/pull/6300

    We fixed a race condition in network topology changes that could cause errors and prevent documents from being correctly indexed. Additionally, we fixed a bug in the networkTopologyChange task batching that was causing it to batch too many task types. We made sure it only batches import tasks, and only those, to avoid out-of-order task processing.

  • Throw document template errors when updating the chat settings by @Kerollmops in https://github.com/meilisearch/meilisearch/pull/6321

    We fixed an issue that prevented the engine from explicitly showing the possible document template errors users could encounter when updating the template in the chat settings. The engine now correctly checks for and throws template errors when they are detected.

  • Fix: Update Index tasks will be properly forwarded to remote nodes by @dureuill in https://github.com/meilisearch/meilisearch/pull/6299

  • Fix action mistake on the chat completions route by @Kerollmops in https://github.com/meilisearch/meilisearch/pull/6290

🔩 Miscellaneous

下载链接