Spring 数据 Elasticsearch 不会从注解隐式创建映射

Spring Data Elasticsearch doesn't implicitly create mapping from annotations

我正在尝试使用 Spring Data Elasticsearch 4.0.1,并试图弄清楚 Elasticsearch 映射是如何以及何时由 Spring 创建的,或者它们是否由 Spring.

如果我有这样的实体:

@Document(indexName = "companies")
public class CompanyEntity {

  @Id
  private final String id;

  @MultiField(
      mainField = @Field(type = Text),
      otherFields = {
          @InnerField(suffix = "raw", type = Keyword)
      }
  )
  private final String companyName;

  @PersistenceConstructor
  public CompanyEntity(String id, String companyName) {
    this.id = id;
    this.companyName = companyName;
  }

  public String getId() {
    return id;
  }

  public String getCompanyName() {
    return companyName;
  }
}

我的印象是 Spring 会隐式地为此索引创建映射,但我似乎弄错了。 Elasticsearch 仍会为此索引创建映射。

{
    "companies": {
        "mappings": {
            "properties": {
                "_class": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "companyName": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "id": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                }
            }
        }
    }
}

从上面可以清楚地看出,InnerField 注释中的后缀没有使用,ignore_above 值也没有使用,因为它默认为 -1,如果尝试设置 Elasticsearch 将完全删除该字段ignore_above 到 -1。

我能够获得上述注释的映射的唯一方法是自己显式设置映射。

@Autowired private ElasticsearchOperations operations;

Document mapping = operations.indexOps(CompanyEntity.class).createMapping();
operations.indexOps(CompanyEntity.class).putMapping(mapping); 

这会产生预期的映射:

{
    "companies": {
        "mappings": {
            "properties": {
                "_class": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "companyName": {
                    "type": "text",
                    "fields": {
                        "raw": {
                            "type": "keyword"
                        }
                    }
                },
                "id": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                }
            }
        }
    }
}

这很好,但我觉得有点奇怪,因为我在官方 Spring Data Elasticsearch docs 中找不到这种方法的任何细节。而且 JavaDocs 有点缺乏任何细节。

这是从 Spring 数据将映射安装到 Elasticsearch 的正确方法吗?

如果您正在使用 ElasticsearchOperations 进行工作,那么这就是创建映射的正确方法。在 4.1 版本中会有一个额外的方法

boolean putMapping(Class<?> clazz)

它结合了创建和写入映射两个步骤。

ElasticsearchOperationsIndexOperations - 或更好的实现 - 是在 Spring 中对 Elasticsearch 的更底层访问 Elasticsearch - 创建索引,放置映射,写入实体等。这些都是基本操作。您可以完全控制执行哪些操作,但执行它们是您的责任。

在此之上构建的是存储库支持。如果定义一个存储库接口

interface CompanyRepository extends ElasticsearchRepository<CompanyEntity, String>{}

您将其注入您的 类

@Autowired CompanyRepository repository;

然后在应用程序启动时 Spring Data Elasticsearch 将创建此接口的实现,并将检查由实体的 @Document 注释定义的索引是否存在。如果不是,它将创建索引并写入映射 - @Document 注释有一个参数 createIndex,默认情况下为 true。

因此,对于自动创建,您必须使用存储库,存储库支持还利用 ElasticsearchOperations 来提供诸如从方法名称派生查询、分页支持等功能。