如何在Elasticsearch中存储布尔数组并执行XOR操作?

时间:2019-03-27 21:55:39

标签: elasticsearch

我想开始使用ElasticSearch保存一些预先计算的结果,这些结果以后需要匹配。此结果是一个200维的位数组,与一个id相关联。

为了执行匹配,我需要在搜索输入和存储的现有元素的位数组之间执行XOR操作,并对保留的位数(基数)进行排序。

是否可以使用无痛或其他脚本策略来做到这一点?如果是的话,用于存储该位数组的最佳映射类型是什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

注意:您可能不应该将其存储为数组,因为数组元素存储为嵌套对象。此外,索引数组不遵守原始顺序。因此,您应该选择将其存储为keyword

进行一些实验,我认为我发现了一些可行的方法(您必须尝试使用​​更大的数字进行验证)。

首先:将其索引为keyword类型,您将需要确保keyword的长度指定了适当的最大长度。

"binary_string" :
   "type" : "keyword",
   "ignore_above" : 256 // <-- Whatever your max binary string length will be
}

第二:然后,您可以使用无痛方式sort基于脚本字段进行查询

GET binary_test/_search
{
  "sort": [
    {
      "_script" : {
            "type" : "string",
            "script" : {
                "lang": "painless",
                "source": """
                def val1 = new BigInteger(doc['binary_string'].value, 2);
                val1.xor(new BigInteger("000000000", 2)).toString(2) // whatever your binary string is that you are comparing to
                """
            },
            "order" : "asc"
        }
    }
  ]
}

注意事项:

  • xor的字符串值进行排序的原因是数字以float的形式存储,最终失去精度可能会导致您的损失。
  • 构造两个BigInteger值并使用BigInteger#xor可能比简单地遍历两个字符串并自己创建一个新字符串要慢,如果您对性能很感兴趣,可以尝试一下。

如果您不关心实际位数,则可以执行以下操作,只需注意位数组长度不匹配(如果您的输入可能这样做)

"_script" : {
   "type" : "number",
       "script" : {
                "lang": "painless",
                "source": """
                def val1 = doc['binary_string'].value;
                def val2 = "000000000"; // <-- the string you care about
                def count = 0;
                for(int i; i < val2.length; i++) {
                  if (val1.charAt(i) != val2.charAt(i)) {
                    count++;
                  }
                }
                count
                """
            },