我有成千上万的文档,如下所示。
{
id: "<some unit test id>",
groupName: "<some group name>",
result: [
1, 0, 1, 1, ... 1
]
}
结果字段是200个数字数组,分别是0或1。
我的工作是根据给定的groupName查找“ group17”和一些数字,例如3、8、27 找到所有文档,其groupName的结果数组元素都等于1,而不论位置3、8、27的值如何。
如果有人可以指出是否可以进行快速搜索,将不胜感激。
答案 0 :(得分:1)
一种实现所需目标的方法是添加另一个字段,该字段包含result
数组中包含的位集的等效整数值,然后使用按位与运算。
例如,假设结果数组为
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]
}
}
}
}
}
如果当前索引在params.ignore
数组中,则第2步首先创建一个长度为11的字符串,该字符串用1或0填充。我们以字符串"10110111110"
结尾。
然后,第3步从该字符串中创建一个BigInteger(在基数2中)。
步骤4逐位比较两个数字,即,只有两个数字在相同位置都带有1时,才会返回文档。
注意:对于长度为200的数组,您需要改为使用IntStream.range(1, 201)
。