在 ElasticSearch 中将新元素推送/添加到嵌套对象数组中的最佳方法是什么?

时间:2021-02-08 08:47:14

标签: php elasticsearch

我有一个候选索引,其中文档的结构如下:

{
  "_index" : "candidates",
  "_type" : "_doc",
  "_id" : "a23OcncBXBMGOH6pwXge",
  "_version" : 1,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "id" : "413",
    "firstname" : "Tania",
    "lastname" : "Stroman",
    "email" : "Berlin@yahoo.com",
    "zip" : "60306",
    "city" : "frankfurt",
    "birthday" : "1978-11-22",
    "tags" : [
      "php",
      "munich"
    ],
    "location" : {
      "lat" : 50.11601257324219,
      "lon" : 8.669955253601074
    }
  }
}

一旦候选人上传了他们的文件,如果它是第一个上传的文件,我会在弹性文档中添加一个名为“文件”的字段。如果文档中已经有上传的文件,我使用以下代码将后续上传的文件推送到现有数组:

public function attachCandidateFile($file)
    {
        $client = ClientBuilder::create()->build();

        $params = [
            'index' => 'candidates',
            'id'    => $file['candidate_id']
        ];

        $candidate = $client->get($params);

        if (!is_array($candidate['_source']['file'])) {
            $candidate['_source']['file'] = [];
        } 
        array_push($candidate['_source']['file'], $file);

        $params = [
            'index' => 'candidates',
            'type'  => '_doc',
            'id'    =>  $file['candidate_id'],   
            'body'  => [
                'doc' => [
                    'file' => $candidate['_source']['file']
                ]
            ]                
           
        ];
        $response = $client->update($params);
        echo '<pre>', print_r($response, true) ,'</pre>';
    } 

有没有办法直接用新对象更新候选人的文件而不需要获取 $candidate['_source']['file'] 以避免覆盖它?

1 个答案:

答案 0 :(得分:0)

当然——当您知道要更新哪个文档时使用 update script(使用其 _id):

POST candidates/_update/a23OcncBXBMGOH6pwXge
{
 "script": {
    "source": """
      if (ctx._source.containsKey('file')) {
        ctx._source.file.add(['filename':params.filename]); // adding a hash map -- could be any JSON primitive
      } else {
        ctx._source.file = [['filename':params.filename]]; // 1-member array
      }
    """,
    "params": {
      "filename": "abc"
    }
  } 
}

或者,使用与上述相同的脚本,但在 _update_by_query call 下。您可以定位该文档(甚至可能是多个文档)无需获取它们

相关问题