【问题标题】:Query to search array for nested matching / not-matching items?查询嵌套匹配/不匹配项的搜索数组?
【发布时间】:2021-06-23 16:00:05
【问题描述】:

对于数组xxx 中的所有对象,我如何编写 DSL 查询来选择具有 JSON 对象的文档,其中字段 configs_1.a_addr 与 configs_2.b_addr 不匹配不?

{
  "name": "steve_doc_45",
  "xxx": [
    {
      "name": "s1",
      "configs_1": {
        "a_addr": "10.1.2.3",
        "a_mask": "255.255.224.0"
      },
      "configs_2": {
        "b_addr": "10.1.2.3",
        "b_mask": "255.255.224.0"
      }
    },
    {
      "name": "s2",
      "configs_1": {
        "a_addr": "10.5.5.5",
        "a_mask": "255.255.224.0"
      },
      "configs_2": {
        "b_addr": "10.6.6.6",
        "b_mask": "255.255.224.0"
      }
    }
  ],
  "other": "stuff"
}

在此示例中,文档应该匹配,因为在名称为 s2 的对象中,值 10.5.5.5 不匹配 10.6.6.6。

如果这个对象从数组xxx中删除,那么这个文档应该不匹配DSL查询,因为名称为s1的对象确实有匹配的字段,然后它是数组 xxx 中唯一的对象。

【问题讨论】:

    标签: elasticsearch-dsl


    【解决方案1】:

    您需要为此使用script 查询。

    查询

    {
      "query": {
        "bool": {
          "filter": {
            "nested": {
              "path": "xxx",
              "query": {
                "script": {
                  "script": """
                        if (doc['xxx.configs_1.a_addr.keyword'].value != doc['xxx.configs_2.b_addr.keyword'].value) 
                        {
                          return true;
                        }
                        return false;
                        """
                }
              }
            }
          }
        }
      }
    }
    

    更新

    在嵌套类型中,数组的每个对象都被视为一个单独的文档,即保持字段之间的关系。

    在对象类型的情况下,字段的多个实例被展平 作为一个无序数组。

    请仔细测试,doc[] 只存储唯一值。如果名称不是唯一的,则循环只会运行一次并跳过第二个对象。

    {
      "query": {
        "script": {
          "script": """
                       for(int i=0; i<doc['xxx.name.keyword'].length; i++)
                       {
                          if (doc['xxx.configs_1.a_addr.keyword'][i] != doc['xxx.configs_2.b_addr.keyword'][i]) 
                          {
                            return true;
                          }  
                       }
                       return false;
    """
        }
      }
    }
    

    【讨论】:

    • 这不起作用:[nested] nested object under path [xxx] is not of nested type 我的数据是原始提取的,没有明确的映射。如果我只是使用上面的脚本而不使用nested,则错误变为No field found for [xxx] in mapping with types []。这是 Elasticsearch 7.5.2,我认为它没有 运行时字段。任何提示如何继续?
    • 问题仍然存在——不管 Elasticsearch 扁平化细微差别如何,您建议的搜索指令在“原始摄取”数据上立即失败,这些数据在没有明确映射指令的情况下上传到 Elasticsearch。
    • "reason": "No field found for [xxx.name.keyword] in mapping with types []
    • 我想我想动态地将这个数组“转换”成可用的东西,而不需要重新索引。 “运行时字段”和“脚本字段”的描述可能是一种前进的方式,但我不熟悉使用它们。另一种方法可能是将每个子数组转换为字符串并进行区分;这可能对我的数据有效,也可能无效。当然,我可以简单地使用其他一些标准进行大规模下载,并按照惯例在客户端处理这个,但这是一个巨大的数据传输,并且在某种程度上违背了 Elasticsearch 中“搜索”的目的。
    • @JohnDB 你能添加你的映射吗?你可以通过 Get /_mapping
    【解决方案2】:

    我无法直接解决此问题。从中长期来看,我打算 (1) 将 Elasticsearch 升级到更新的版本,以及 (2) 重构索引以使用显式映射,这样我就可以利用 @JaspreetChahal 的好建议。

    同时,在短期内,我修补了数据源上传器以显式检查此条件并将注释添加到消息字段(字符串数组)中,然后我可以使用 DSL 查询字符串查询直接搜索- 也带有通配符。这行得通。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多