1

我必须更新我的 ES 文档中的一些字段。

我有一个整数“objectID”字段,它是文档所涉及的对象的唯一 ID。

我有一个 String 'objectType' 字段,它是文档所关注的对象类型。

所有文档都描述了对对象的操作,并且 objectType 和 objecID 始终存在于所有文档中。

不幸的是,一些objectType为“post_image”的文档已被索引为“post”。objectID 仍然是唯一且有效的,并且只有一种类型的文档具有错误的 objectType。因此,所有对象至少有另一个具有正确 objectType 和相同唯一 objectID 的文档。

我想使用 update_by_query 在 objectType 为“post”且 objectID 位于 objectType 为“post_image”的任何其他文档中的所有文档上将 objectType 的值更新为“post_image”。

这是我的伪代码脚本:

{
"query": {
    "match" : { "objectType" : "post" } //all documents with objectType post
},
"script": {
    "lang": "painless",
  "source": "
//subquery selecting all objectIDs from documents with objectType "post_image"
    subQueryResults = "query": {
        "match" : { "objectType" : "post_image" }
        //I don't know to filter results to retrive objectID field only
        //no need for help here, i'll figure it out myself
    }
    if (/*ctx.source['objectID'] in subQueryResults*/){
        ctx._source['objectType'] = "post_image"
    }

  "
}

我是无痛脚本的新手,我不知道如何在我的脚本中放置另一个查询以获取所有“post_image”ID 的列表。我知道我可以将参数传递给脚本,但我也不知道是否或如何使用查询结果。

谢谢!

编辑:

我已经通过使用 Kibana 原始导出提取相关 objectID 的 csv 列表解决了我的部分问题,并且我制作了一个 PHP 脚本来解析每个 objectID 并将其放入我的查询字符串中以用于我的 update_by_query,它只是找到具有匹配 objectID 的所有文档并将 objectType 字段值替换为“post_image”。

我正在使用 php curl 进行这些调用,尽管在我的请求中使用了“冲突”:“继续”,但我遇到了版本冲突问题。我已经在 kibana 的开发控制台中测试了相同的查询,它运行良好,我找不到任何解释为什么它在从 php 运行时不更新我的文档。

这是脚本:

<?php
$query = "";
$csvFile = file($argv[1]);
try{
        //$data = array();
    $query = "";
    $i = 0;
    $csv_headers = array();

    $uri = "http://ip/index/type/_update_by_query";

    $conn = curl_init();
    curl_setopt($conn, CURLOPT_URL, $uri);
    curl_setopt($conn, CURLOPT_TIMEOUT, 5);
    curl_setopt($conn, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($conn, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($conn, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($conn, CURLOPT_FAILONERROR, FALSE);
    curl_setopt($conn, CURLOPT_CUSTOMREQUEST, strtoupper('POST'));
    curl_setopt($conn, CURLOPT_FORBID_REUSE, 0);

    foreach ($csvFile as $line) {
        try{    
            //WARNING: separator parameter of str_getcsv call is a risk or error based on the type of CSV used. 
            //skip header in CSV
            if ($i > 0){
                $data = str_getcsv($line,',');
                    //$data = explode(",", $line);
                $id = $data[0];
                echo $id.", ";
            //old query, wasn't working
            //     $query = "{
            //         \"conflicts\": \"proceed\",
            //         \"query\": {
            //             \"match\" : { \"objectID\" : ".$id."
            //         }
            //     },
            //     \"script\": {
            //         \"lang\": \"painless\",
            //         \"source\": \"ctx._source['objectType'] = '".$argv[2]."'\"
            //     }
            // }";
                $query = "{
                    \"conflicts\": \"proceed\",
                    \"query\": {
                       \"bool\": {
                        \"must\": {
                            \"match\": {
                                \"objectType\": \"Post\"
                            }
                        },
                        \"filter\": {
                            \"terms\": {
                                \"objectID\": [
                                    ".$id."
                                ]
                            }
                        }
                    }
                },
                \"script\": {
                    \"lang\": \"painless\",
                    \"source\": \"ctx._source['objectType'] = 'Post_image'\"
                }
            }";

            curl_setopt($conn, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($query))
        );
            curl_setopt($conn, CURLOPT_POSTFIELDS, json_encode($query));
            $response = curl_exec($conn);
            //sleep(1);
            echo $response;
        }
        $i++;
    }catch(Exception $e){
        echo $e->getMessage();
            //continue;
    }
}catch(Exception $e){
echo $e->getMessage();
}
}
echo $query;
echo "\nCompleted.\n\n";
?>

示例响应:

{"index":"index",
"type":"type",
"id":"AWB0YFcjAFB9uQAwMSKx",
"cause":{"type":"version_conflict_engine_exception",
"reason":"[type][AWB0YFcjAFB9uQAwMSKx]: version conflict,
 current version [27] is different than the one provided [26]",
"index_uuid":"yOD9SBy0RMmDZGK_N5o8qw",
"shard":"2",
"index":"index"},
"status":409}

这很奇怪,因为我没有在我的请求中提供任何文档版本。或许它与 upbade_by_query API 的一些自动内部行为有关。

4

1 回答 1

2

我最终解决了整个想法。

首先,我修改了我的查询:

$query = "{ \"query\": {
                       \"bool\": {
                        \"must\": {
                            \"match\": {
                                \"objectType\": \"Post\" <- more optimal!
                            }
                        },
                        \"filter\": {
                            \"term\": {
                                \"objectID\":
                                    \"".$id."\"
                            }
                        }
                    }
                },
                \"script\": {
                    \"lang\": \"painless\",
                    \"source\": \"ctx._source['content'] = '".$argv[2]."'\"
                }
            }";

argv[2] 是我想提供给我的文档的 objectType。(“Post_image”)

然后,我必须删除 curl_exec 之前的 JSON_encode($query)

curl_setopt($conn, CURLOPT_POSTFIELDS, $query);
        $response = curl_exec($conn);

然后我停止了错误,但是我有很多空结果,这很奇怪,因为在使用 kibana 开发工具时查询正在返回结果,但后来我意识到我使用了错误的 IP,并将所有内容发送到另一个启动并运行的测试 ES相同的索引/类型,但索引中没有任何实际文档,因此空结果没有实际错误。我觉得有点傻。

PS:功能请求:facepalm 表情符号。

于 2018-01-23T16:17:14.093 回答