【问题标题】:Spring Data Elasticsearch doesn't implicitly create mapping from annotationsSpring Data Elasticsearch 不会隐式地从注解创建映射
【发布时间】:2020-08-21 02:24:08
【问题描述】:

我正在尝试使用 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,如果尝试将 ignore_above 设置为 -1,Elasticsearch 将完全删除该字段。

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

@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 Data 将映射安装到 Elasticsearch 的正确方法吗?

【问题讨论】:

  • 1.使用 sprint-data-elastic (3.2.9.RELEASE) 创建了一个示例项目,并使用多字段(文本、关键字)定义了文档映射并运行了该项目。生成的映射是我所期望的。您能否分享您正在使用的 spring-data-elastic 和 elastic-search 的版本。
  • 2.你可以在 ElasticsearchRestTemplate -> "putMapping(String indexName, String type, Object mapping)" 上设置一个调试点,看看生成了什么映射。
  • 3.这是将映射从 Spring Data 安装到 Elasticsearch 的正确方法吗? - Es 不像 Mysql where-in 如果该字段在商店中不存在,你会得到一个异常,而是如果没有找到它会创建一个新字段。因此,只要您正确定义它并且生成的映射是您想要的,就可以通过 spring 数据安装映射。我能回答你所有的问题吗?
  • @SahilGupta,我使用的版本是 4.0.1。预期的映射是我在帖子中详细介绍的最后一个映射。我详细介绍的第一个映射是 Elasticsearch 自动创建的映射。我将尝试在 Spring 方面进行一些调试,以查看是否正在创建任何映射。关于您的最后一点,我知道我可能必须手动创建映射,但这确实打破了使用 Spring-Data 的期望。我正在尝试了解是否需要始终手动创建这些映射,因为此详细信息不在官方春季文档中。

标签: java spring spring-boot elasticsearch spring-data-elasticsearch


【解决方案1】:

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

boolean putMapping(Class<?> clazz)

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

ElasticsearchOperationsIndexOperations - 或者更好的实现 - 是 Spring Data Elasticsearch 中对 Elasticsearch 的更低级别的访问 - 创建索引、放置映射、编写实体等。这些是基本操作。您可以完全控制执行哪些操作,但执行这些操作是您的责任。

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

interface CompanyRepository extends ElasticsearchRepository<CompanyEntity, String>{}

你在你的一个类中注入的

@Autowired CompanyRepository repository;

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

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

【讨论】:

  • 嘿@P.J.Meisch,我的期望是Spring会自动为我创建这个映射,正如你在倒数第二段中提到的那样。但我发现情况并非如此。没错,索引是由 Spring 创建的,但是 Elasticsearch 正在为索引而不是 Spring 创建映射。使 Entity 类上的注释生效的唯一方法是,如果我在索引本身上手动 putMapping,这有点不是我所期望的。我不想问这个问题,但是您是否有一个示例 repo 来演示 Spring 无需手动创建的映射?
  • 嘿@P.J.Meisch,我能够解决这个问题。我的 Elasticsearch 配置类中存在配置问题,因此 Spring 上下文没有获取我的配置。我解决了这个问题,然后在添加存储库后,我能够看到预期的映射。这在官方文档中是否有详细说明,存储库对于创建映射是强制性的?除了我详细介绍的简单示例之外,我还有一个更复杂的问题,无法使用典型的存储库来解决我的查询需求。我手动创建查询并使用 NativeSearchQuery 执行。
  • @Document 注释的文档和 javadoc 声明索引创建是在存储库引导时完成的。我认为下一个版本添加一个关于索引管理的部分会很好,因为 4.1 添加了模板等功能并改进了别名处理。让我成为一个问题。
  • 嘿@P.J.Meisch,我使用的是spring-data 4.1.3,通过存储库(如您的示例)使用弹性操作,但在应用程序启动时创建的索引有一个空映射。只在保存文件时填充,由elastic填充。有什么想法吗?
  • 您的实体的属性是否用@Field 注释?这些属性有getter和setter方法吗?
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 2016-04-11
  • 2021-12-12
  • 1970-01-01
  • 2021-07-17
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多