如何按嵌套类型的数组大小进行过滤?

2023-12-02

假设我有以下类型:

{
    "2019-11-04": {
        "mappings": {
            "_doc": {
                "properties": {
                    "labels": {
                        "type": "nested",
                        "properties": {
                            "confidence": {
                                "type": "float"
                            },
                            "created_at": {
                                "type": "date",
                                "format": "strict_date_optional_time||date_time||epoch_millis"
                            },
                            "label": {
                                "type": "keyword"
                            },
                            "updated_at": {
                                "type": "date",
                                "format": "strict_date_optional_time||date_time||epoch_millis"
                            },
                            "value": {
                                "type": "keyword",
                                "fields": {
                                    "numeric": {
                                        "type": "float",
                                        "ignore_malformed": true
                                    }
                                }
                            }
                        }
                    },
                    "params": {
                        "type": "object"
                    },
                    "type": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}

我想按尺寸/长度进行过滤labels大批。我尝试过以下方法(正如官方文档所建议的):

{
    "query": {
        "bool": {
            "filter": {
                "script": {
                    "script": {
                        "source": "doc['labels'].size > 10"
                    }
                }
            }
        }
    }
}

但我不断得到:

{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "runtime error",
        "script_stack": [
          "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:81)",
          "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:39)",
          "doc['labels'].size > 10",
          "    ^---- HERE"
        ],
        "script": "doc['labels'].size > 10",
        "lang": "painless"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "2019-11-04",
        "node": "kk5MNRPoR4SYeQpLk2By3A",
        "reason": {
          "type": "script_exception",
          "reason": "runtime error",
          "script_stack": [
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:81)",
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:39)",
            "doc['labels'].size > 10",
            "    ^---- HERE"
          ],
          "script": "doc['labels'].size > 10",
          "lang": "painless",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "No field found for [labels] in mapping with types []"
          }
        }
      }
    ]
  },
  "status": 500
}

恐怕这不可能,因为领域labels不是 ES 保存或创建倒排索引的字段。

Doc doc['fieldname']仅适用于创建倒排索引的字段,Elasticsearch 的 Query DSL 也仅适用于创建倒排索引的字段,不幸的是nested类型不是创建倒排索引的有效字段。

话虽如此,我有以下两种方法可以做到这一点。

为了简单起见,我创建了示例映射、文档和两个可能对您有所帮助的解决方案。

Mapping:

PUT my_sample_index
{
  "mappings": {
    "properties": {
      "myfield": {
        "type": "nested",
        "properties": {
          "label": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

样本文件:

// single field inside 'myfield'
POST my_sample_index/_doc/1
{
  "myfield": {                              
    "label": ["New York", "LA", "Austin"]   
  }
}


// two fields inside 'myfield' 
POST my_sample_index/_doc/2
{                                          
  "myfield": {                             
    "label": ["London", "Leicester", "Newcastle", "Liverpool"],
    "country": "England"
  }
}

解决方案1:使用脚本字段(在应用程序级别进行管理)

我有一个解决方法可以得到你想要的东西,虽然不完全是,但可以帮助你过滤掉你的服务层或应用程序。

POST my_sample_index/_search
{
  "_source": "*", 
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ]
    }
  },
  "script_fields": {
    "label_size": {
        "script": {
            "lang": "painless",
            "source": "params['_source']['labels'].size() > 1"
        }
    }
  }
}

您会注意到,作为响应,有一个单独的字段label_size被创建为true or false value.

响应示例如下所示:

{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_sample_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "myfield" : {
            "label" : [
              "New York",
              "LA",
              "Austin"
            ]
          }
        },
        "fields" : {
          "label_size" : [              <---- Scripted Field
            false
          ]
        }
      },
      {
        "_index" : "my_sample_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "myfield" : {
            "country" : "England",
            "label" : [
              "London",
              "Leicester",
              "Newcastle",
              "Liverpool"
            ]
          }
        },
        "fields" : {                  <---- Scripted Field
          "label_size" : [
            true                      <---- True because it has two fields 'labels' and 'country'
          ]
        }
      }
    ]
  }
}

请注意,只有第二个文档才有意义,因为它有两个字段,即country and labels。但是,如果您只想使用以下文档label_size with true,这必须在您的应用程序层进行管理。

解决方案2:重新索引与 labels.size 使用脚本处理器

创建一个新索引,如下所示:

PUT my_sample_index_temp
{
  "mappings": {
    "properties": {
      "myfield": {
        "type": "nested",
        "properties": {
          "label": {
            "type": "keyword"
          }
        }
      },
      "labels_size":{             <---- New Field where we'd store the size
        "type": "integer"
      }
    }
  }
}

创建以下管道:

PUT _ingest/pipeline/set_labels_size
{
  "description": "sets the value of labels size",
  "processors": [
      {
        "script": {
          "source": """
            ctx.labels_size = ctx.myfield.size();
          """
        }
      }
    ]
}

使用 Reindex API 重新索引my_sample_index index

POST _reindex
{
  "source": {
    "index": "my_sample_index"
  },
  "dest": {
    "index": "my_sample_index_temp",
    "pipeline": "set_labels_size"
  }
}

验证文件my_sample_index_temp using GET my_sample_index_temp/_search

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_sample_index_temp",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "labels_size" : 1,           <---- New Field Created 
          "myfield" : {
            "label" : [
              "New York",
              "LA",
              "Austin"
            ]
          }
        }
      },
      {
        "_index" : "my_sample_index_temp",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "labels_size" : 2,           <----- New Field Created
          "myfield" : {
            "country" : "England",
            "label" : [
              "London",
              "Leicester",
              "Newcastle",
              "Liverpool"
            ]
          }
        }
      }
    ]
  }
}

现在您可以简单地使用这个字段labels_size在你的查询中,它的方式更容易,更不用说高效了。

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何按嵌套类型的数组大小进行过滤? 的相关文章

随机推荐

  • iOS 9 数字键盘中看不到完成按钮的问题

    此代码在 ios 6 7 8 中工作 但在 ios 9 中调用了所有方法 但它不可见 在数字键盘上 这是我的代码 import ViewController h define TAG BUTTON DONE 67125 interface
  • MariaDB:我可以在不使用“AS”的情况下检索重复的列名吗

    我有很多使用的表id作为主键 当我将几张桌子连接在一起并且select 仅显示 id 列之一 使用 MySql 时 解决这个问题的唯一方法是使用SELECT AS 例如SELECT id AS groupId MariaDB 仍然是这种情况
  • 使用 Order By 时 COALESCE 出现奇怪的 TSQL 行为 [重复]

    这个问题在这里已经有答案了 我在合并方面有一些非常奇怪的行为 当我没有指定返回金额 TOP 50 时 我只会得到一个最后结果 但如果我删除 排序依据 它就会起作用 下面的示例 DECLARE result varchar MAX SELEC
  • Xcode - 创建 csv/电子表格文件

    我有三个数组 第一个数组包含字符串 与第二个数组相同 但第三个数组包含NSNumber的 无论如何 回到主题 我怎样才能创建一个像电子表格一样的 csv 这是一个 Excel 数字 文件来包含这些数据 是否可以 这是我的三个数组 locat
  • 在 Haskell 中列出 9 个选项中所有可能的 4 个选项

    我无法找到一种有效的方法来从 Haskell 的 9 个元素列表中选出 4 个元素的所有排列 python way 做同样的事情 itertools permutations range 9 1 4 在 Haskell 中 一种不太有效的方
  • ##__VA_ARGS__ 在 C99 下参数为零时不吞咽逗号

    我想使用如下宏 define x y a VA ARGS b 像这样扩展 x gt y a b x 1 gt y a 1 b With std gnu99 它工作完美 With std c99然而 它看起来像这样 x gt y a b x
  • 没有实现接口的所有方法。是否可以?

    有什么办法可以NOT在继承类中实现接口的所有方法 解决这个问题的唯一方法是将您的班级声明为abstract并将其留给子类来实现缺少的方法 但最终 链中必须有人实现它才能满足接口契约 如果你确实不需要特定的方法 你可以实现它 然后return
  • 从逗号连接列表创建 SQL 表

    我正在运行 SQL Server 并且有一个存储过程 我想做一个带有 WHERE IN 子句的 select 语句 我不知道列表会有多长 所以现在我尝试了以下方法 SELECT FROM table1 WHERE id IN idList
  • 应用内结算/应用内购买中项目的最大限制

    我想知道 Android 和 iPhone 的应用内结算中最多可以放置多少项目 我记得好像读过3000左右 但找不到参考资料 另外 如果 3000 是最大值 那么解决这个问题的合法方法是什么 我的应用程序将出售内容 我认为解决该问题的一种可
  • 在 docker 中构建 Meteor 应用程序时,“您已以 root 身份运行 Meteor”

    我在 dockerfile 中构建了 Meteor 应用程序映像 RUN meteor build directory meteor app 并遇到以下错误 Step 11 RUN meteor build directory meteor
  • 为什么 VS Code 显示“仅限windll Windows:Creates ()”智能感知建议?

    在 VS Code 上编写 Python 代码时 它会显示如下建议 仅windll Windows 创建 我试图看看这是否来自我可能已经安装的代码片段扩展 但我认为我没有任何 任何人都可以解释为什么我得到他的代码完成废话吗 我每次都遇到同样
  • 在Windows C++中禁用键盘?

    How can I completely disable the keyboard using c in windows And by completely disable I mean so even Ctrl Alt Delete do
  • OpenCV 如何将相机畸变应用于图像

    我有一个渲染图像 我想将径向和切向畸变系数应用于从 opencv 获得的图像 即使有不失真功能 也没有失真功能 如何使用畸变系数来扭曲图像 我也在寻找相同类型的功能 我找不到 所以我自己实现了 这是 C 代码 首先 您需要使用焦距和中心标准
  • C++中二进制数到十进制数的转换

    我尝试构建一个函数 将存储在字符串中的二进制数计算为存储在long long 我认为我的代码应该可以工作 但事实并非如此 在此示例中 对于二进制数101110111小数是375 但我的输出完全令人困惑 这是我的代码 include
  • UIImageView 上的 UIGestureRecognizer

    我有一个UIImageView 我希望能够调整大小和旋转等 Can a UIGestureRecognizer被添加到UIImageView 我想添加一个旋转和捏合识别器UIImageView它将在运行时创建 如何添加这些识别器 检查一下u
  • 检测应用程序是否是从 Play 商店安装的

    我想检查并允许使用我的应用程序 前提是它是从 Play 商店下载的 并且尚未被其他用户或从任何其他来源共享 如果应用程序不是从 Google Play 商店下载的 如何阻止用户使用该应用程序 此方法将检查您的应用程序是否已从 Play 商店
  • matplotlib 对数轴:仅显示 10 的幂

    我有一个双对数图 x 轴范围从 10 9 到 10 12 这是我第一次发帖 所以我无法发布我的情节的图片 我想更改 x 和 y 轴 以便仅显示 10 的幂 x 轴上的数字类似于 9 10 11 12 I used matplotlib ti
  • 如何将带有单引号的varchar传递给Oracle中的存储过程[重复]

    这个问题在这里已经有答案了 我有这样的存储过程 调用 packagename StoredProc A B 然后 A B 部分将用作 IN 子句中过程代码中的参数 当我使用 in 子句运行该代码时paramvalue IN A B 它按预期
  • 密码字段的正则表达式

    我需要一个密码字段的正则表达式 必须有 1 个号码 必须有 1 个字母 大写 必须有 1 个字母 小写 长度必须至少 8 个字符 只能包含字母和数字字符 到目前为止我有 d a z A Z 8 这满足了我上面的大部分条件 但我如何限制它只允
  • 如何按嵌套类型的数组大小进行过滤?

    假设我有以下类型 2019 11 04 mappings doc properties labels type nested properties confidence type float