Один из способов добиться того, чего вы хотите, - это добавить другое поле, которое содержит эквивалентное целочисленное значение набора битов, содержащегося в массиве result
, а затем использовать побитовую операцию AND.
Например, скажем,что результирующий массив равен
result: [1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0]
Целочисленное значение, представленное этими битами, равно 1470, поэтому я сохраняю следующий документ:
PUT test/doc/1
{
"groupName": "group12",
"result": [
1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0
],
"resultLong": "1470"
}
Теперь запрос будет выглядеть следующим образом
POST test/_search
{
"query": {
"script": {
"script": {
"source": """
// 1. create a BigInt out of the resultLong value we just computed
def value = new BigInteger(doc['resultLong'].value.toString());
// 2. create a bitset filled with 1's except for those positions specified in the ignore parameters array
def comp = IntStream.range(1, 12).mapToObj(i -> params.ignore.contains(i - 1) ? "0" : "1").collect(Collectors.joining());
// 3. create a BigInt out of the number we've just created
def compare = new BigInteger(comp, 2);
// 4. compare both using a bitwise AND operation
return value.and(compare).equals(compare);
""",
"params": {
"ignore": [1, 4, 10]
}
}
}
}
}
Шаг 2 сначала создает строку длиной 11, заполненную 1 или 0, если текущий индекс находится в массиве params.ignore
.В итоге получается строка "10110111110"
.
. На шаге 3 из этой строки создается BigInteger (в базе 2).
На шаге 4 сравниваются оба числа по битам, т. Е. Документбудет возвращено только в том случае, если оба числа имеют 1 в одинаковых позициях.
Примечание: для массивов длины 200 вместо него необходимо использовать IntStream.range(1, 201)
.