添加文档时 Meilisearch 报
index_primary_key_no_candidate_found或index_primary_key_multiple_candidates_found,根因是未显式指定 primaryKey 且文档中找不到唯一以id结尾的字段。解法是在 POST 文档时传?primaryKey=字段名,或创建索引时设primaryKey参数。适用 Meilisearch 全版本。
Issue & Env(案发现场与环境)
- 业务场景:往一个新建索引 POST 文档,API 返回
taskUid,但轮询任务状态发现是failed,错误码是index_primary_key_no_candidate_found。或者文档里同时有id和author_id两个字段,报index_primary_key_multiple_candidates_found。 - 环境:Meilisearch v1.54.3,curl / 任意 SDK。
- 关键区分:这不是文档格式错误,也不是字段类型错误,是 Meilisearch 无法从文档字段名中自动推断出 primary key。
StackTrace(堆栈日志)
场景一:文档中没有以 id 结尾的字段。官方文档给出的完整错误响应:
{
"uid": 1,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 5,
"indexedDocuments": null
},
"error": {
"message": "The primary key inference failed as the engine did not find any field ending with `id` in its name. Please specify the primary key manually using the `primaryKey` query parameter.",
"code": "index_primary_key_no_candidate_found",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#index-primary-key-no-candidate-found"
},
"duration": "PT0.006579S",
"enqueuedAt": "2026-10-02T10:19:14.464858Z",
"startedAt": "2026-10-02T10:19:14.465369Z",
"finishedAt": "2026-10-02T10:19:14.471948Z"
}
场景二:文档中有多个以 id 结尾的字段(如 id 和 author_id):
{
"uid": 4,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 5,
"indexedDocuments": 5
},
"error": {
"message": "The primary key inference failed as the engine found 2 fields ending with `id` in their names: 'id' and 'author_id'. Please specify the primary key manually using the `primaryKey` query parameter.",
"code": "index_primary_key_multiple_candidates_found",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#index-primary-key-multiple-candidates-found"
},
"duration": "PT0.006002S",
"enqueuedAt": "2026-10-02T10:44:42.625574Z",
"startedAt": "2026-10-02T10:44:42.626041Z",
"finishedAt": "2026-10-02T10:44:42.632043Z"
}
两种情况下文档都不会被索引,indexedDocuments 为 null 或 0。
Reproduce(复现代码)
场景一:文档没有以 id 结尾的字段:
curl -X POST 'http://localhost:7700/indexes/books/documents' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '[
{"title": "Solaris", "author": "Stanislaw Lem", "isbn": "978-0156014000"},
{"title": "Dune", "author": "Frank Herbert", "isbn": "978-0441013594"}
]'
# 返回 taskUid,但任务状态为 failed
# 文档字段:title, author, isbn —— 没有以 id 结尾的字段
场景二:文档有多个以 id 结尾的字段:
curl -X POST 'http://localhost:7700/indexes/books/documents' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '[
{"id": 1, "title": "Solaris", "author_id": 42},
{"id": 2, "title": "Dune", "author_id": 43}
]'
# 字段:id, title, author_id —— 两个以 id 结尾,无法自动推断
Root Cause(根因分析)
自动推断规则
Meilisearch 要求每个索引有一个 primary key——每个文档中唯一标识自身的字段。如果创建索引时没有显式指定,Meilisearch 会尝试从第一个文档中自动推断。官方文档原文:
Suppose you add documents to an index without previously setting its primary key. In this case, Meilisearch will automatically look for an attribute ending with the string
idin a case-insensitive manner (for example,uid,BookId,ID) in your first document and set it as the index’s primary key.
推断逻辑是字段名以 id 结尾(不区分大小写)。匹配的字段如 id、uid、movieId、product_id、ID 都可以作为候选。
两种失败场景
- 无候选:文档中没有任何以
id结尾的字段(如只有title、author、isbn)。Meilisearch 找不到候选,抛出index_primary_key_no_candidate_found。 - 多候选:文档中有多个以
id结尾的字段(如id和author_id)。Meilisearch 无法确定用哪个,抛出index_primary_key_multiple_candidates_found。
两种情况下文档添加任务都会失败,文档不会被索引。这是有意为之——primary key 一旦设定且有文档存在就不能更改,所以推断不确定时宁可不索引。
推断只看第一个文档
Meilisearch 只检查第一批文档的第一个文档对象来确定 primary key。如果第一个文档有 id 字段但后续文档缺少该字段,会报另一个错误 missing_document_id,而不是推断失败。
The Fix(解决方案)
方式一:POST 文档时传 primaryKey 查询参数(最快)
curl -X POST 'http://localhost:7700/indexes/books/documents?primaryKey=isbn' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '[
{"title": "Solaris", "author": "Stanislaw Lem", "isbn": "978-0156014000"}
]'
primaryKey 参数只在索引为空(首次添加文档)时生效。如果索引已有 primary key,传这个参数不会改变它。
方式二:创建索引时显式指定 primaryKey
curl -X POST 'http://localhost:7700/indexes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '{
"uid": "books",
"primaryKey": "isbn"
}'
# 返回 taskUid,等待 task succeeded 后再添加文档
方式三:已有索引用 PATCH 修改 primaryKey
curl -X PATCH 'http://localhost:7700/indexes/books' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '{"primaryKey": "isbn"}'
注意:primary key 一旦设置且索引中有文档,不能直接更改。必须先删除所有文档,再修改 primary key,再重新添加。
注意事项
- primary key 值只能是整数或字符串,字符串只能含字母数字(a-z A-Z 0-9)、连字符(
-)和下划线(_)。 - 同一索引内 primary key 值必须唯一,重复值会覆盖之前的文档。
- 最佳实践:创建索引时就指定 primaryKey,不依赖自动推断,避免首批文档格式不统一导致的推断失败。
References(参考来源)
- Primary key — Meilisearch 官方文档meilisearch-docs
- Primary key — Meilisearch 官方内部文档meilisearch-docs
- Error codes — Meilisearch 官方文档meilisearch-docs
- Error Format and Definitions — Meilisearch 规范文档meilisearch-spec
- Quick start — Meilisearch 官方文档meilisearch-docs
