我想开始使用ElasticSearch保存一些预先计算的结果,这些结果以后需要匹配。此结果是一个200维的位数组,与一个id相关联。
为了执行匹配,我需要在搜索输入和存储的现有元素的位数组之间执行XOR操作,并对保留的位数(基数)进行排序。
是否可以使用无痛或其他脚本策略来做到这一点?如果是的话,用于存储该位数组的最佳映射类型是什么?
谢谢!
答案 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
"""
},