春季数据Elasticsearch不会从注释中隐式创建映射。

huangapple go评论144阅读模式
英文:

Spring Data Elasticsearch doesn't implicitly create mapping from annotations

问题

我正在尝试使用Spring Data Elasticsearch 4.0.1,并试图弄清楚Elasticsearch映射是由Spring创建还是由Spring创建的,以及何时创建。

如果我有一个实体类如下:

```java
@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文档中找不到关于这种方法的任何细节。而且JavaDocs中几乎没有任何详细信息。

这是从Spring Data中安装映射到Elasticsearch的正确方法吗?


<details>
<summary>英文:</summary>

I&#39;m trying to work with Spring Data Elasticsearch 4.0.1 and trying to figure out how and when the Elasticsearch mappings are being created by Spring or if they are being created by Spring.

If I have an entity like so:

@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;
}
}


I was under the impression that Spring would implicitly create the mapping for this index but I seem to be mistaken.  Elasticsearch still creates the mapping for this index.  

{
"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
}
}
}
}
}
}
}


Clearly from the above, the suffix in the InnerField annotation is not used and the ignore_above value is not used as well since it defaults to -1, and Elasticsearch would remove this field altogether if trying to set ignore_above to -1.

The only way I was able to get the mapping for the above annotations was to explicitly set the mapping myself. 

@Autowired private ElasticsearchOperations operations;

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


Which yields the expected 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
}
}
}
}
}
}
}


Which is fine, but feels a bit odd to me as I could not find any details of this approach in the official [Spring Data Elasticsearch docs][1].  And the JavaDocs are kinda void of any details.

Is this the right approach to installing mappings into Elasticsearch from Spring Data?


  [1]: https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.mapping

</details>


# 答案1
**得分**: 3

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

    boolean putMapping(Class<?> clazz)

该方法将创建和写入映射的两个步骤结合在一起。

`ElasticsearchOperations`和`IndexOperations` - 或者更好的说是它们的实现 - 是在Spring Data Elasticsearch中访问Elasticsearch的更低级别的方式,比如创建索引、放置映射、写入实体等。这些是基本操作。您完全控制哪些操作被执行,但是执行这些操作是您的责任。

在此基础上是仓库支持。如果您定义一个仓库接口:

    interface CompanyRepository extends ElasticsearchRepository<CompanyEntity, String> {}

并且在您的某个类中注入它:

    @Autowired CompanyRepository repository;

那么在应用程序启动时,Spring Data Elasticsearch将创建该接口的实现,并检查实体的`@Document`注解定义的索引是否存在。如果不存在,它将创建索引并写入映射 - `@Document`注解有一个参数`createIndex`,默认值为true。

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

<details>
<summary>英文:</summary>

If you are using the `ElasticsearchOperations` to work with, then this is the right way to create the mapping. In version 4.1 there will be an additional method

    boolean putMapping(Class&lt;?&gt; clazz)

which combines the two steps of creating and writing the mapping.

 `ElasticsearchOperations` and `IndexOperations` - or better the implementations - are the more low level access to Elasticsearch in Spring Data Elasticsearch - create an index, put the mapping, write an entity etc. These are elemantary operations. You have the full control which operations are executed, but it&#39;s your respsonsibility to execute them.

Building on top of that is the repository support. If you define a repository interface 

    interface CompanyRepository extends ElasticsearchRepository&lt;CompanyEntity, String&gt;{}

which you inject in one of your classes

    @Autowired CompanyRepository repository;

then on application startup Spring Data Elasticsearch will create an implementation of this interface and will check if the index defined by the entity&#39;s `@Document` annotation exists. If not, it will create the index and write the mapping - The `@Document` annotation has an argument `createIndex` which by default is true.

So for autocreation you must use the repository, the repository support also makes use of the `ElasticsearchOperations` to offer things like query derivation from method names, paging support and more.

</details>



huangapple
  • 本文由 发表于 2020年8月21日 10:24:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63515615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定