0

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

我的索引映射如下所示:

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

我的文件如下所示:

{
  "testField":"123abc"
}

或者

{
  "testField": "456789"
}

我试过查询:

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

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

4

2 回答 2

1

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

下面的摄取管道包含一个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"
        }
      }
    }
  ]
}

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

{
  "query": {
    "range": {
      "numField": {
        "gte": 0,
        "lte": 2000000
      }
    }
  }
}
于 2019-05-09T04:21:37.730 回答
1

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;
                  }
              """
            }
          }
        }
      ]
    }
  }
}

希望能帮助到你!

于 2019-05-08T22:40:51.697 回答