【问题标题】:How to convert binary data back to a float array in Elasticsearch/painless如何在 Elasticsearch/painless 中将二进制数据转换回浮点数组
【发布时间】:2019-07-25 23:35:51
【问题描述】:

我正在尝试在 elasticsearch 6.7 中有效地存储和检索浮点数组。 Numeroc doc 值已排序,这意味着我不能直接使用它们。

一开始我是用source这个字段的值,但是在大型查询上性能不是很好。

我尝试将浮点数组编码为二进制并在我的脚本中对其进行解码。不幸的是,我坚持将byte[4] 数组转换为painless 中的float

在 Java 中是这样的

Float.intBitsToFloat((vector_bytes[3] << 24) | ((vector_bytes[2] & 0xff) << 16) |  ((vector_bytes[1] & 0xff) << 8) |  (vector_bytes[0] & 0xff));

但是用&amp; 0xff 丢弃标志会毫无痛苦地抛出"Illegal tree structure."

知道如何做到这一点吗?

小例子:

设置索引

# Minimal example binary array
# Create the index
PUT binary_array 
{
  "mappings" : {
      "_doc" : {
          "properties" : {
              "vector_bin": { "type" : "binary", "doc_values": true },
              "vector": { "type" : "float" }
          }
      }
  }
}
# Put two documents
PUT binary_array/_doc/1
{
  "vector": [1.0, 1.1, 1.2],
  "vector_bin": "AACAP83MjD+amZk/"
}
PUT binary_array/_doc/2
{
  "vector": [3.0, 2.1, 1.2],
  "vector_bin": "AABAQGZmBkCamZk/"
}

样本搜索将二进制数组转换回数组

GET binary_array/_search
{
  "script_fields": {
    "vector_parsed": {
      "script": {
        "source": """
        def vector_bytes = doc["vector_bin"].value.bytes;
        def vector = new float[vector_bytes.length/4];
        for (int i = 0; i < vector.length; ++i) {
          def n = i*4;
          // This would be the Java way, discarding the sign of bytes 0-2, but is raises a "Illegal tree structure." in painless
          //def intBits = (vector_bytes[n+3] << 24) | ((vector_bytes[n+2] & 0xff) << 16) |  ((vector_bytes[n+1] & 0xff) << 8) |  (vector_bytes[n] & 0xff);
          // This runs but gives incorrect results
          def intBits = (vector_bytes[n+3] << 24) | ((vector_bytes[n+2] ) << 16) |  ((vector_bytes[n+1] ) << 8) |  (vector_bytes[n] );
          vector[i] = Float.intBitsToFloat( intBits );
        }
        return vector;
        """
      }
    },
    "vector_src": {
      "script": """params._source["vector"]"""
    }
  }
}

【问题讨论】:

    标签: elasticsearch elasticsearch-6 elasticsearch-painless


    【解决方案1】:

    经过更多调查后,我意识到按位和在 painless 中确实有效,但 0xff 不适用。

    这解决了我的问题:

    Float.intBitsToFloat( (vector_bytes[n+3] << 24) | ((vector_bytes[n+2] & 255) << 16) |  ((vector_bytes[n+1] & 255) << 8) |  (vector_bytes[n] & 255) )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-26
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 2016-12-25
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      相关资源
      最近更新 更多