从Elasticsearch文档中移除字段

icomxhvb  于 2023-01-29  发布在  ElasticSearch
关注(0)|答案(8)|浏览(207)

我需要删除所有索引到Elasticsearch的文档中的一个字段。我该怎么做?

k0pti3hp

k0pti3hp1#

@backtrack告诉的是真的,但是接下来在Elasticsearch中有一个非常方便的方法来做到这一点,Elasticsearch会抽象出删除的内部复杂性,你需要使用update API来实现这一点--

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.remove(\"name_of_field\")"
}'

您可以在here中找到更多文档。
注意:从Elastic Search 6开始,您需要包含一个内容类型标头:

-H 'Content-Type: application/json'
gfttwv5a

gfttwv5a2#

Elasticsearch在2.3中添加了update_by_query,这个实验性的接口允许您对所有匹配查询的文档进行更新。
internally elasticsearch做一个扫描/滚动来收集成批的文档,然后像批量更新界面一样更新它们,由于没有网络和序列化的开销,这比用你自己的扫描/滚动界面手动做要快,每个记录都必须加载到ram中,修改然后写入。
昨天,我从ES集群中删除了一个大字段,在update_by_query期间,我看到了每秒10,000条记录的持续吞吐量,这是由CPU而不是IO限制的。
如果群集有其他更新流量,请考虑设置conflicts=proceed,否则当更新其中一个批处理下的一个记录时,整个作业将在遇到ConflictError时停止。
类似地,设置wait_for_completion=false将导致update_by_query通过tasks接口运行,否则,如果连接关闭,作业将终止。
网址:

http://localhost:9200/INDEX/TYPE/_update_by_query?wait_for_completion=false&conflicts=proceed

POST主体:

{
  "script": "ctx._source.remove('name_of_field')",
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "name_of_field"
          }
        }
      ]
    }
  }
}

从Elasticsearch 1.43开始,内联groovy scripting is disabled by default。你需要通过在配置文件中添加script.inline: true来启用它,这样的内联脚本才能工作。
或者将groovy作为脚本上传,并使用"script": { "file": "scriptname", "lang": "groovy"}

x9ybnkn6

x9ybnkn63#

您可以使用**_update_by_query**

实施例1

索引:我的索引
字段:user.email

POST my_index/_update_by_query?conflicts=proceed
{
    "script" : "ctx._source.user.remove('email')",
    "query" : {
        "exists": { "field": "user.email" }
    }
}

实施例2

索引:我的索引
字段:项目总数

POST my_index/_update_by_query?conflicts=proceed
{
    "script" : "ctx._source.remove('total_items')",
    "query" : {
        "exists": { "field": "total_items" }
    }
}
1sbrub3j

1sbrub3j4#

前面的答案对我不起作用。
我不得不添加关键字“内联”:

POST /my_index/_update_by_query
{
  "script": {
    "inline": "ctx._source.remove(\"myfield\")"
  },
  "query" : {
      "exists": { "field": "myfield" }
  }
}
h4cxqtbf

h4cxqtbf5#

默认情况下这是不可能的,因为现在Lucene还不支持,基本上你只能从Lucene索引中放入或删除整个Lucene文档。
1.获取文档的第一版
1.删除字段
1.推送此新版本的文档
此答案对版本〈ES 5有效。

bqujaahr

bqujaahr6#

对于那些坚持使用bulk API的人来说,实现文档字段删除的替代方法是在批量API调用的update操作负载中提供额外的脚本。
命令部分与官方文档中描述的相同:

curl -s -H "Content-Type: application/x-ndjson"  -H "Accept: application/json; indent=4;" \
     --data-binary   '@es_bulk_edit_data.json'  --request POST \
     "http://YOUR_ELASTICSEARCH_HOST:PORT_NUM/OPTIONAL_INDEX/OPTIONAL_TYPE/_bulk?pretty"

在请求体文件中,同一张单据可能需要使用2个有效载荷,一个是用于新建、更新字段,另一个是用于通过脚本删除字段,可能如下:

// assume you attempt to add one field `artist`, update one field `num_views`,
// and delete one field `useless` in the document with type t1 and ID 123
{"update": {"_type": "t1", "_id": "123"}}
{"doc": {"artist": "new_artist", "num_views": 67}}
{"update": {"_type": "t1", "_id": "123"}}
{"script": {"source": "ctx._source.remove(params.del_field_name)", "lang":"painless", "params":{"del_field_name": "useless"}}}

注:

  • 在批量API中,doc部分不能与script部分放在同一个有效载荷中,ElasticSearch似乎拒绝处理这样的有效载荷结构,并返回错误响应400 bad request,原因消息将是Validation Failed: 1: can't provide both script and doc;。这就是为什么我将删除和所有其他操作分开在2个有效载荷中。
  • 在版本5.6和6.6上进行了测试,在最新版本(v7.10)中也应获得相同结果
i7uaboj4

i7uaboj47#

PUT /products/_update/1
{
  "docs" :{
    "price": 12,
    "quantity": 3,
    "in_stock": 6
  }
}

Now if I need to remove "quantity" then:

POST products/_update/1
{
  "script": {
    "source": "ctx._source.remove(\"quantity\")"
  }
}
irtuqstp

irtuqstp8#

我想在前面的回答中补充一点,删除字段后,索引的大小不会改变.将不得不创建一个新的索引或使用_reindex API。

curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
 "source": {
   "index": "old-index"
 },
 "dest": {
   "index": "new-index"
}}

'

相关问题