搜索数组值(位置列表除外)

时间:2019-03-02 03:47:21

标签: elasticsearch

我有成千上万的文档,如下所示。

{
    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的值如何。

如果有人可以指出是否可以进行快速搜索,将不胜感激。

1 个答案:

答案 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)