如何在Elasticsearch重新索引无痛脚本中生成UUID

时间:2019-02-14 02:20:55

标签: elasticsearch elasticsearch-painless

我正在尝试使用reindex api创建一组文档的副本。文档的字段之一(uuid)是UUID。我需要复制的文档在uuid字段中具有新的UUID。

根据[1]和[2],方法java.util.UUID.randomUUID()未列入白名单,可用于无痛脚本。

问题:

1)如何轻松生成UUID?

2)为什么UUID.randomUUID()被认为是不安全的操作?还是只是没有被列入白名单的疏忽?

3)如何在UUID.randomUUID()上下文中将"reindex"列入白名单?我根据[3]中的示例尝试构建自己的elasticsearch无痛扩展/插件来实现此目的。问题在于它仅适用于"SearchScript"上下文。似乎没有等效的"ReindexContext"

这是我正在尝试的简化版本:

curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "product1"
  },
  "dest": {
    "index": "product2"
  },
  "script": {
    "source": "ctx._source.uuid = java.util.UUID.randomUUID().toString()",
    "lang": "painless"
  }
}
'

哪个会产生以下错误:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "script_exception",
        "reason" : "compile error",
        "script_stack" : [
          "... rce.uuid = java.util.UUID.randomUUID().toString()",
          "                             ^---- HERE"
        ],
        "script" : "ctx._source.uuid = java.util.UUID.randomUUID().toString()",
        "lang" : "painless"
      }
    ],
    "type" : "script_exception",
    "reason" : "compile error",
    "script_stack" : [
      "... rce.uuid = java.util.UUID.randomUUID().toString()",
      "                             ^---- HERE"
    ],
    "script" : "ctx._source.uuid = java.util.UUID.randomUUID().toString()",
    "lang" : "painless",
    "caused_by" : {
      "type" : "illegal_argument_exception",
      "reason" : "method [java.util.UUID, randomUUID/0] not found"
    }
  },
  "status" : 500
}

我知道我的方法是有效的,并且上面提到的是一个轻松的白名单问题,因为当我尝试其他方法(fromString())时,我不会出错:

curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "product1"
  },
  "dest": {
    "index": "product2"
  },
  "script": {
    "source": "ctx._source.uuid = java.util.UUID.fromString(\u0027ad139caa-5b54-4179-b812-5015daecad1e\u0027).toString()",
    "lang": "painless"
  }
}
'

参考文献:

[1]-https://discuss.elastic.co/t/generate-a-uuid-using-randomuuid-in-painless/144354/3

[2]-https://www.elastic.co/guide/en/elasticsearch/painless/6.6/painless-api-reference.html

[3]-https://github.com/elastic/elasticsearch/tree/v6.6.0/plugins/examples/painless-whitelist

其他说明:

3 个答案:

答案 0 :(得分:1)

我解决此问题的功能请求已在此处接受并实现:https://github.com/elastic/elasticsearch/issues/39080

答案 1 :(得分:0)

You can simply do the following,

curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "product1"`enter code here`
  },
  "dest": {
    "index": "product2"
  },
  "script": {
    "source": "ctx._id=ctx._id+1",
    "lang": "painless"
  }
}
'
ctx._id = will always give you a new id and plus 1 will generate the new one.

这只是通过添加后缀获取唯一ID的解决方案

答案 2 :(得分:0)

最直接的方法是使用自写函数,这是我的。当然,这只是一种解决方法,但在大多数情况下应该会有所帮助。

# your data is stored as X, Y, Z
print(X.shape, Y.shape, Z.shape)

x1, y1, z1 = X.flatten(), Y.flatten(), Z.flatten()
x1y1, x1x1, y1y1 = x1*y1, x1*x1, y1*y1

X_data = np.array([x1, y1, x1y1, x1x1, y1y1]).T  # X_data shape: n, 5
Y_data = z1

from sklearn import linear_model

reg = linear_model.LinearRegression().fit(X_data, Y_data)

print("coefficients of equation of plane, (a1, a2, a3, a4, a5): ", reg.coef_)

print("value of intercept, c:", reg.intercept_)

将其复制到脚本中,如果需要带破折号且小写的UUID,则可以通过调用String generateUUID(boolean addDashes, boolean upperCase) { def chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; def dashIndices = [7, 11, 15, 19]; def sb = new StringBuilder(); def r = new Random(); for (def pos = 0; pos < 32; pos += 1) { sb.append(chars[r.nextInt(16)]); if (addDashes && dashIndices.contains(pos)) { sb.append('-'); } } def result = sb.toString(); return upperCase ? result.toUpperCase() : result; } 来获取UUID。