【问题标题】:How can I find all documents in elasticsearch that contain a number in a certain field?如何在 elasticsearch 中找到包含某个字段中的数字的所有文档?
【发布时间】:2019-05-08 21:43:41
【问题描述】:

我有一个keyword 类型的字段,可以包含数字或字符串。如果该字段不包含任何字母,我想点击该文档。我该怎么做?

我的索引映射如下:

{
  "mappings": {
    "Entry": {
      "properties": {
        "testField": {
          "type": "keyword"
        }
      }
    }
  }
}

我的文档如下所示:

{
  "testField":"123abc"
}

{
  "testField": "456789"
}

我试过查询:

{
  "query": {
    "range": {
      "gte": 0,
      "lte": 2000000
    }
  }
}

但它仍然命中123abc。我该如何设计,以便我只点击该特定字段中带有数字的文档?

【问题讨论】:

    标签: elasticsearch elasticsearch-query elasticsearch-mapping


    【解决方案1】:

    还有另一个更理想的选择可以准确地实现您想要的。您可以利用 ingest API pipelines 并使用 script processor 在索引时创建另一个数字字段,然后在搜索时更有效地使用。

    下面的摄取管道包含一个 script 处理器,它将创建另一个名为 numField 的字段,该字段仅包含数值。

    POST _ingest/pipeline/_simulate
    {
      "pipeline": {
        "processors": [
          {
            "script": {
              "source": """
              ctx.numField = /\D/.matcher(ctx.testField).replaceAll("");
              """
            }
          }
        ]
      },
      "docs": [
        {
          "_source": {
            "testField": "123"
          }
        },
        {
          "_source": {
            "testField": "abc123"
          }
        },
        {
          "_source": {
            "testField": "123abc"
          }
        },
        {
          "_source": {
            "testField": "abc"
          }
        }
      ]
    }
    

    用 4 个混合了字母数字内容的不同文档模拟此管道,将产生以下结果:

    {
      "docs" : [
        {
          "doc" : {
            "_index" : "_index",
            "_type" : "_type",
            "_id" : "_id",
            "_source" : {
              "numField" : "123",
              "testField" : "123"
            },
            "_ingest" : {
              "timestamp" : "2019-05-09T04:14:51.448Z"
            }
          }
        },
        {
          "doc" : {
            "_index" : "_index",
            "_type" : "_type",
            "_id" : "_id",
            "_source" : {
              "numField" : "123",
              "testField" : "abc123"
            },
            "_ingest" : {
              "timestamp" : "2019-05-09T04:14:51.448Z"
            }
          }
        },
        {
          "doc" : {
            "_index" : "_index",
            "_type" : "_type",
            "_id" : "_id",
            "_source" : {
              "numField" : "123",
              "testField" : "123abc"
            },
            "_ingest" : {
              "timestamp" : "2019-05-09T04:14:51.448Z"
            }
          }
        },
        {
          "doc" : {
            "_index" : "_index",
            "_type" : "_type",
            "_id" : "_id",
            "_source" : {
              "numField" : "",
              "testField" : "abc"
            },
            "_ingest" : {
              "timestamp" : "2019-05-09T04:14:51.448Z"
            }
          }
        }
      ]
    }
    

    索引您的文档using this pipeline 后,您可以在numField 而不是testField 上运行范围查询。与其他解决方案相比(抱歉@Kamal),它将脚本负担转移到在索引时每个文档只运行一次,而不是在搜索时每次在每个文档上运行。

    {
      "query": {
        "range": {
          "numField": {
            "gte": 0,
            "lte": 2000000
          }
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      Afaik,Elasticsearch 对此没有直接的解决方案。

      相反,您需要写一个Script Query。以下是您要查找的内容:

      POST <your_index_name>/_search
      {
        "query": {
          "bool": {
            "must": [
              {
                "script": {
                  "script": {
                    "lang": "painless", 
                    "source": """
                        try{           
                          String temp = doc['testField'].value;
                          int a = Integer.parseInt(temp);
                          if(a instanceof Integer)
                            return true;
                        }catch(NumberFormatException e){
                          return false;
                        }
                    """
                  }
                }
              }
            ]
          }
        }
      }
      

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2014-06-07
        • 2016-03-31
        • 1970-01-01
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        • 1970-01-01
        相关资源
        最近更新 更多