如何处理 Elasticsearch 索引中的空值

How to handle nulls in an Elasticsearch index

我有一个 SQL table 正在导出到 Elasticsearch。

其中一列是可以为 null 的数字字段,在某些记录中有 null。

当我们尝试索引 table 时,我们得到这个错误:

One of the ETL (BigQuery -> ElasticSearch) jobs for Table : MLS has been ES Failed Chunk of 10000 from index 20000 possibly due to incompatible objects.

Failing BigQuery Table: MLS

Stack Trace of the error:

Traceback (most recent call last): File "/Users/asif/zodiacbackend/zodiacbackend/tasks.py", line 205, in insertIntoES helpers.bulk(es, doc_generator(dataframe,table)) File "/Users/asif/zodiacbackend/env/lib/python3.7/site-packages/elasticsearch/helpers/actions.py", line 300, in bulk for ok, item in streaming_bulk(client, actions, *args, **kwargs): File "/Users/asif/zodiacbackend/env/lib/python3.7/site-packages/elasticsearch/helpers/actions.py", line 230, in streaming_bulk **kwargs File "/Users/asif/zodiacbackend/env/lib/python3.7/site-packages/elasticsearch/helpers/actions.py", line 158, in _process_bulk_chunk raise BulkIndexError("%i document(s) failed to index." % len(errors), errors) elasticsearch.helpers.errors.BulkIndexError: ('2 document(s) failed to index.', [{'index': {'_index': 'mls', '_type': 'mls', '_id': 'b100qHABEFI45Lp-z3Om', 'status': 400, 'error': {'type': 'illegal_argument_exception', 'reason': 'mapper [Lot_Size_Sq_Ft] of different type, current_type [text], merged_type [long]'}, 'data': { 'Lot_Size_Sq_Ft': Decimal('13504')}}}]) 

如何让系统识别空值?

您正在处理一个常见的 ES 头挠头。 Elasticsearch doesn't index null values(不仅仅是数字空值)。您需要在索引映射中指定您希望如何为任何检测到的空值编制索引。像这样:

  "mappings": {
    "properties": {
      "nullable_numeric": {
        "type":       "integer",
        "null_value": -1 
      },
      "nullable_text": {
       "type":        "text",
       "null_value":  "NULL"
    }
  }

一旦你这样做,ES 就会知道如何正确地索引这些字段。请注意,您不需要更改原始数据,只需让 ES 知道如何为搜索索引空值....顺便说一句,当您查询 ES 时不会影响文档。

用户 WittyID,错过了一些重要的事情,例如:

  1. null_value 的值必须与您的字段具有相同的数据类型,因此在他的示例中,他声明了 integer 字段但将 NULL 定义为 null_values, 会抛出 json_parse_exception 并且这在 official link 中被称为 important 如下:

The null_value needs to be the same data type as the field. For instance, a long field cannot have a string null_value.

  1. null_value 仅影响数据的索引方式,它不会修改 _source 文档,因此在您的源文档中,无论您传递什么,都将被存储,而不是提到的那个在 null_values 参数和查询时,您还需要使用值 null_value 参数。.

简而言之,ES 无法识别 null,因此您可以为 null 定义自定义值,然后使用它来索引和查询 null values.It 使用下面的示例很容易解释整个事情,任何人都可以尝试:

创建索引

{
  "mappings": {
    "properties": {
      "my_signed_integer": {
        "type":"integer",
        "null_value": -1 --> note we defining `null` values as `-1`.
      }
    }
  }
}

索引文件

  1. 存储null整数文档

    { "my_number":空 }

如果您从 ES 获取此文档,它将返回如下:

{
   "_index": "so-6053847",
   "_type": "_doc",
   "_id": "1",
   "_version": 1,
   "_seq_no": 0,
   "_primary_term": 1,
   "found": true,
   "_source": {
      "my_number": null. --> As explained earlier, in source its stored as `null`.
   }
}
  1. 索引非负值

    { "my_number":10 }

搜索查询以获取具有 null 个值的整数

{
  "query": {
    "term": {
      "my_signed_integer": -1 -->notice same `null_value`, you need to mention
    }
  }
}

结果:

 "hits": [
         {
            "_index": "so-6053847",
            "_type": "_doc",
            "_id": "1",
            "_score": 1.0,
            "_source": {
               "my_signed_integer": null --> notice it shows `null`, not `-1`
            }
         }
      ]

搜索查询其他号码(非空)即在我们的例子中 10

{
  "query": {
    "term": {
      "my_signed_integer": 10
    }
  }
}

结果

"hits": [
         {
            "_index": "so-6053847",
            "_type": "_doc",
            "_id": "2",
            "_score": 1.0,
            "_source": {
               "my_signed_integer": 10 -->source matches the indexed value for this doc
            }
         }
      ]