#elasticsearch
#elasticsearch
Вопрос:
Я хотел бы начать использовать ElasticSearch для сохранения некоторых предварительно вычисленных результатов, которые мне нужно будет сопоставить впоследствии. Этот результат представляет собой 200-размерный битовый массив, связанный с идентификатором.
Чтобы выполнить сопоставление, мне нужно было бы выполнить операцию XOR между входными данными поиска и сохраненными битовыми массивами для моих существующих элементов и отсортировать по количеству оставшихся битов (мощность).
Возможно ли это вообще, используя безболезненные или другие стратегии написания сценариев? И если да, то какой тип сопоставления лучше всего использовать для хранения этого bitarray?
Спасибо!
Ответ №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
может быть медленнее, чем простое перебирание двух строк и самостоятельное создание новой, я бы поэкспериментировал с этим, если вы заботитесь о производительности.
Если вас не волнует фактическое число битов, вы могли бы сделать следующее, просто будьте осторожны с несоответствием длины bitarray (если это возможно при вашем вводе)
"_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
"""
},