在 Mapping 里面,将 dynamic 参数设置成 strict 可以拒绝索引包含未知字段的文档。 此条 Tips 由 medcl 贡献。

如何填充新增字段里的值

Elasticsearch | 作者 DimonHo | 发布于2017年04月14日 | 阅读数:7082

现在为了实现一个这样的需求,某个字段A是设置了分词查询的,现在想新增一个B字段,设置不分词,但内容要和A字段内容一样,如果是SQL就是这样的:update tableName set B=A; 翻译成elasticsearch语句该怎么写?
已邀请:

kennywu76 - Wood

赞同来自: DimonHo

如果ES版本是2.x或者5.x,通过update-by-query结合script可以达到类似的效果。 以5.x结合painless script为例:
# 创建分词字段foo 
PUT test
{
"mappings": {
"test": {
"properties": {
"foo": {
"type": "text"
}
}
}
}
}

# 索引一条文档
POST test/test?refresh
{
"foo": "shout out loud"
}

# 增加一个不分词字段foo_raw
PUT test/test/_mapping
{
"test": {
"properties": {
"foo_raw": {
"type": "keyword"
}
}
}
}

# 搜索foo_raw字段无匹配
POST test/_search
{
"query": {
"term": {
"foo_raw": "shout out loud"
}
}
}

# 通过update-by-query,用painless脚本将所有文档的foo字段赋值给foo_raw字段
POST test/_update_by_query?refresh
{
"query": {
"match_all": {}
},
"script": {
"inline": "ctx._source['foo_raw'] = ctx._source['foo']"
}
}

#再次搜索foo_raw字段,有结果,证实赋值成功
POST test/_search
{
"query": {
"term": {
"foo_raw": "shout out loud"
}
}
}

{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "AVtxM-mFv8wSnZufUqd0",
"_score": 0.2876821,
"_source": {
"foo_raw": "shout out loud",
"foo": "shout out loud"
}
}
]
}
}

值得注意的是,执行update-by-script的时候,会对query match的文档做一个snapshot,只更新snapshot里的文档,因此这个过程如果有新数据写入,新数据不会被更新。
 
这种更新的方法的优点是无需重建已有的索引,但是因为使用了脚本做更新,在数据量很大的情况下,性能可能不会很好。
 
比较而言,重新索引的性能会好得多,es的reindex api使用起来也很方便。 如果可以接受更换索引名称的话,还是重建比较好。

Jea - 一只猿

赞同来自:

无解, 因为string类型的是默认走了索引的, 就算用updateAPI来搞
 
去重建索引吧

Jea - 一只猿

赞同来自:

错别字...string默认走分词

fhyes123 - ES小白

赞同来自:

不懂一楼为啥要说无解,楼主是说另外建一个字段不分词,并不是修改原有字段的属性
思路是:建立字段B不分词,用深度分页去遍历字段A,把数据写到字段B
但是一定要注意同步的问题,就是写入数据的时候字段AB要同时写入,检索的时候根据具体需求检索A或者B就行了

要回复问题请先登录注册