【问题标题】:Search for array values except for a list of positions搜索除位置列表之外的数组值
【发布时间】:2019-03-05 01:51:07
【问题描述】:

我有数以千万计的文件,如下所示。

{
    id: "<some unit test id>",
    groupName: "<some group name>",
    result: [
        1, 0, 1, 1, ... 1
    ]
}

结果字段是一个 200 的数字数组,0 或 1。

我的工作是给定一个组名,比如“group17”和一些数字,比如 3、8、27 查找 groupName 的结果数组元素都等于 1 的所有文档,忽略位置 3、8、27 处的值。

如果有人能指出是否有快速搜索,将不胜感激。

【问题讨论】:

  • 不清楚你所说的...disregarding the values at positions 3, 8, 27是什么意思...因为你希望他们是1
  • 这意味着搜索应该忽略那些位置的值(在这种情况下是 3,8,27),只根据其他位置的值做出决定。
  • 好的,所以它应该只在除位置 3、8 和 27 之外的所有值都是 1 的情况下返回文档吗?团体呢?哪些组应该匹配?
  • 好问题!我编辑了问题以反映 groupName 的输入参数。希望现在清楚了。
  • groups的映射类型是什么? nested 我希望 ;-)

标签: elasticsearch


【解决方案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 然后从该字符串(以 2 为基数)创建一个 BigInteger。

第 4 步逐位比较两个数字,即仅当两个数字在相同位置都为 1 时才会返回文档。

注意:对于长度为 200 的数组,您需要使用 IntStream.range(1, 201) 代替。

【讨论】:

  • 感谢@val 的回答。 2个问题。 a) 1470 这个数字是从哪里来的? 1470 甚至不能被 8 整除。 b) 想知道如果我有 1000 万个这样的文档,是否有性能估计?几秒钟?几分钟?
  • 10110111110(二进制)= 1470(十进制)。不知道它在 10M 文档上的表现如何(没有给出)。有其他约束可能有助于减少脚本应该在其上运行的文档集。
  • 那你是在修改文档吗?这样就不需要读取整个result 数组了吗?
  • 我不知道你想怎么处理,我只是说在索引时你应该在数组之外添加resultLong字段,以便于查询.数组的问题在于它不能直接在脚本中使用,因为它只能通过 doc 值访问,它将值从 0 到 1 排序,因此您丢失了位定位。
  • @Val,结果数组的长度是可变的,范围从200到500。不知道我们如何将这么多位转换为整数。
猜你喜欢
  • 2021-05-19
  • 1970-01-01
  • 2021-03-13
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 2016-02-19
相关资源
最近更新 更多