Как я могу найти все документы вasticsearch, которые содержат число в определенном поле? - PullRequest
0 голосов
/ 09 мая 2019

У меня есть поле типа keyword, которое может содержать либо число, либо строку. Если поле не содержит букв, я хотел бы нажать на этот документ. Как я могу это сделать?

Мое отображение индекса выглядит так:

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

Мои документы выглядят так:

{
  "testField":"123abc"
}

или

{
  "testField": "456789"
}

Я пробовал запрос:

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

, но он все еще поражает 123abc. Как я могу сделать так, чтобы я нажимал только на документы с номером в этом поле?

Ответы [ 2 ]

1 голос
/ 09 мая 2019

Существует еще один более оптимальный вариант для достижения именно того, что вы хотите. Вы можете использовать конвейеры API ingest , а с помощью 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
      }
    }
  }
}
1 голос
/ 09 мая 2019

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...