主字段 (Primary Field)
Meilisearch 中的索引是文档的集合。文档由字段组成,每个字段包含一个属性和对应的值。
主字段是一个特殊字段,必须存在于所有文档中。它的属性是**主键,其值是文档ID。它唯一标识索引中的每个文档,确保同一个索引中不可能存在两个完全相同的文档**。
假设我们有一个书籍索引。每个文档包含多个字段,记录书籍的作者、标题和价格等数据。更重要的是,每个文档都包含一个主字段,由索引的主键id和一个唯一ID组成。
[
{
"id": 1,
"title": "Diary of a Wimpy Kid: Rodrick Rules",
"author": "Jeff Kinney",
"genres": ["comedy","humor"],
"price": 5.00
},
{
"id": 2,
"title": "Black Leopard, Red Wolf",
"author": "Marlon James",
"genres": ["fantasy","drama"],
"price": 5.00
}
]
除了主键之外,同一个索引中的文档不需要共享其他属性。这个数据集中的一本书可以缺少title或genre属性,只要它有id属性,仍然可以被 Meilisearch 成功索引。
主键 (Primary Key)
主键是主字段的属性。
每个索引都有一个主键,这是该索引中所有文档必须共享的属性。如果你尝试向索引添加文档时,即使只有一个文档缺少主键,所有文档都不会被存储。
{
"id": 1,
"title": "Diary of a Wimpy Kid",
"author": "Jeff Kinney",
"genres": ["comedy","humor"],
"price": 5.00
}
在上述索引中,每个文档都通过一个主字段进行标识,该字段包含主键 id 和唯一的文档 id 值。
文档 ID
文档 ID 是与主键关联的值。它作为主字段的一部分,是给定索引中每个文档的唯一标识符。
索引中的两个文档可以拥有除主键外所有属性相同的值。如果同一索引中的两个文档具有相同的 ID,它们将被视为同一文档,前一个文档会被覆盖。
Meilisearch 中的文档添加请求是原子性的。这意味着即使批次中只有一个文档的主字段值格式不正确,也会导致错误,Meilisearch 将不会索引该批次中的任何文档。
正确格式:
错误格式:
文档 ID 格式要求
文档 ID 必须是整数或字符串。如果是字符串,则只能包含字母数字字符(a-z、A-Z、0-9)、连字符(-)和下划线(_)。
设置主键
您可以显式设置主键,或让 Meilisearch 从数据集中推断主键。无论选择哪种方式,一个索引同一时间只能有一个主键,且当索引中存在文档时无法更改主键。
在创建索引时设置主键
手动创建索引时,可以显式指定该索引要使用的主键。
以下代码创建名为 books 的索引,并将 reference_number 设置为其主键:
curl \
-X POST 'MEILISEARCH_URL/indexes' \
-H 'Content-Type: application/json' \
--data-binary '{
"uid": "books",
"primaryKey": "reference_number"
}'
{
"taskUid": 1,
"indexUid": "books",
"status": "enqueued",
"type": "indexCreation",
"enqueuedAt": "2022-09-20T12:06:24.364352Z"
}
在添加文档时设置主键
当向空索引添加文档时,您可以在文档添加请求中显式设置索引的主键。
以下代码向 books 索引添加文档并将 reference_number 设为该索引的主键:
curl \
-X POST 'MEILISEARCH_URL/indexes/books/documents?primaryKey=reference_number' \
-H 'Content-Type: application/json' \
--data-binary '[
{
"reference_number": 287947,
"title": "Diary of a Wimpy Kid",
"author": "Jeff Kinney",
"genres": [
"comedy",
"humor"
],
"price": 5.00
}
]'
响应:
{
"taskUid": 1,
"indexUid": "books",
"status": "enqueued",
"type": "documentAdditionOrUpdate",
"enqueuedAt": "2022-09-20T12:08:55.463926Z"
}
使用更新索引接口更改主键
当索引中已存在文档时,无法更改主键。若要更改已有文档索引的主键,您必须先删除所有文档,然后更改主键,最后重新添加文档。
以下代码将主键更新为 title:
curl \
-X PATCH 'MEILISEARCH_URL/indexes/books' \
-H 'Content-Type: application/json' \
--data-binary '{ "primaryKey": "title" }'
响应:
{
"taskUid": 1,
"indexUid": "books",
"status": "enqueued",
"type": "indexUpdate",
"enqueuedAt": "2022-09-20T12:10:06.444672Z"
}
Meilisearch 自动推断主键
假设您在未预先设置主键的情况下向索引添加文档。此时 Meilisearch 会自动在第一个文档中查找以 id 结尾(不区分大小写)的属性(例如 uid、BookId、ID),并将其设为索引的主键。
如果 Meilisearch 发现多个以 id 结尾的属性或找不到合适的属性,将会抛出错误。这两种情况下,文档添加过程都会中断,不会有任何文档被添加到索引中。
主键错误
本节介绍一些主键错误及其解决方法。
index_primary_key_multiple_candidates_found
当首次向索引添加文档时,如果 Meilisearch 发现多个以 id 结尾的属性,就会发生此错误。可以通过手动设置索引的主键来解决。
{
"uid": 4,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 5,
"indexedDocuments": 5
},
"error": {
"message": "主键推断失败,因为引擎发现名称以 `id` 结尾的 2 个字段:'id' 和 'author_id'。请使用 `primaryKey` 查询参数手动指定主键。",
"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": "2023-01-17T10:44:42.625574Z",
"startedAt": "2023-01-17T10:44:42.626041Z",
"finishedAt": "2023-01-17T10:44:42.632043Z"
}
index_primary_key_no_candidate_found
当您首次向索引添加文档时,如果所有文档都不包含以 id 结尾的属性,就会发生此错误。可以通过手动设置索引的主键或确保所有添加的文档都具有 id 属性来解决此问题。
{
"uid": 1,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 5,
"indexedDocuments": null
},
"error": {
"message": "主键推断失败,因为引擎没有找到任何名称以 `id` 结尾的字段。请使用 `primaryKey` 查询参数手动指定主键。",
"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": "2023-01-17T10:19:14.464858Z",
"startedAt": "2023-01-17T10:19:14.465369Z",
"finishedAt": "2023-01-17T10:19:14.471948Z"
}
invalid_document_id
当文档 ID 不符合正确格式时会出现此错误。文档 ID 只能是整数或字符串类型,且只能包含字母数字字符 a-z A-Z 0-9、连字符 - 和下划线 _。
{
"uid": 1,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 5,
"indexedDocuments": null
},
"error": {
"message": "文档标识符 `1@` 无效。文档标识符只能是整数或字符串类型,且只能包含字母数字字符 (a-z A-Z 0-9)、连字符 (-) 和下划线 (_)。",
"code": "invalid_document_id",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#invalid_document_id"
},
"duration": "PT0.009738S",
"enqueuedAt": "2021-12-30T11:28:59.075065Z",
"startedAt": "2021-12-30T11:28:59.076144Z",
"finishedAt": "2021-12-30T11:28:59.084803Z"
}
missing_document_id
当索引已设置主键,但尝试添加的文档中缺少该属性时会出现此错误。
{
"uid": 1,
"indexUid": "books",
"status": "failed",
"type": "documentAdditionOrUpdate",
"canceledBy": null,
"details": {
"receivedDocuments": 1,
"indexedDocuments": null
},
"error": {
"message": "文档缺少 `id` 属性: `{\"title\":\"Solaris\",\"author\":\"Stanislaw Lem\",\"genres\":[\"science fiction\"],\"price\":5.0.",
"code": "missing_document_id",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#missing_document_id"
},
"duration": "PT0.007899S",
"enqueuedAt": "2021-12-30T11:23:52.304689Z",
"startedAt": "2021-12-30T11:23:52.307632Z",
"finishedAt": "2021-12-30T11:23:52.312588Z"
}