12

问题

我正在尝试将布尔值保存到 elasticsearch,但它为 NULL 特别有效。在这种情况下有点不在乎。

似乎有几种选择,但尚不完全清楚最好的选择是什么。

我们正在使用 ElasticSearch 5.0.2 版

选项1

最简单的方法是将其保存为具有 NULL 值的布尔值。这些将被 ES 视为“缺失”。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "my_boolean": { "type": "boolean"}
      }
    }
  }
}

PUT my_index/my_type/1
{"my_boolean": true}

PUT my_index/my_type/2
{"my_boolean": false}

PUT my_index/my_type/3
{"my_boolean": null}

这有几个问题,其中之一是聚合。似乎没有一种简单的方法来获取 values和true聚合。falseNULL

我知道该missing功能,所以我知道我可以执行以下操作:

GET my_index/_search
{
  "size":0,
  "aggregations": {
    "my_boolean": {
      "terms": {
        "field": "my_boolean"
      }
    },
    "missing_fields": {
          "missing" : {
            "field": "my_boolean"
          }
    }
  }
}

但这将导致一个具有 2 个值(真/假)的存储桶和丢失文档的单独计数。这看起来会引起问题。

选项 2

另一种选择是实际给 NULL 一个值,如 手册中所述。问题是该值需要是正确的类型,并且只有 true 和 false 作为布尔值。

null_value 需要与字段的数据类型相同。例如,长字段不能有字符串 null_value。

这意味着我们可以使用支持超过 2 个值的不同类型,例如整数,但这在我的脑海中就像说:让我们将其映射为整数,并将 1 定义为 true,2 定义为 false,3 定义为 null。这会起作用,但我们会有一个所有人都应该知道的隐式映射。(所有生产者/消费者/whatyamahaveits)。

选项 3

最终版本是尝试编写脚本来解决这个问题。

GET my_index/_search
{
  "size":0,
  "aggregations": {

    "my_boolean": {
      "terms": {
       "script" : {
        "inline": "if(doc['my_boolean'].length === 1) { if(doc['my_boolean'].value === true){ return 1;} else {return 2;} } else { return 3;}"
        }
      }
    }
  }
}

现在我们确实在有些理智的情况下得到了正确的结果。

"aggregations": {
"my_boolean": {
  "doc_count_error_upper_bound": 0,
  "sum_other_doc_count": 0,
  "buckets": [
    {
      "key": "1",
      "doc_count": 1
    },
    {
      "key": "2",
      "doc_count": 1
    },
    {
      "key": "3",
      "doc_count": 1
    }
  ]
}
}

请注意,我们在这里仍然有一个与键的隐式映射,所以这似乎与将其映射为整数有一些相同的问题。但是,您的数据类型仍然是它应该是的,所以这可能是某种东西。请注意,我们不能将存储桶以“null”作为键。我们当然可以称它们为“true”、“false”和“null”(字符串),但这是同样的情况,但隐藏得更多。

问题

处理这个空问题的最佳方法是什么? (或者也许我们应该称之为“三态布尔问题”?)

澄清一下:我们担心以后“非标准”值可能会导致问题。我们首先看到的是分桶,我们可能可以使用上面的脚本解决方案来修复它,但也许我们稍后会遇到其他问题。因此,我们正在寻找保存此类数据的最佳实践,而不是针对特定问题的快速解决方案。

4

2 回答 2

5

您可以使用聚合的missing设置terms(即不是单独的聚合missing)。

这样,您可以继续使用您的布尔字段并获得 0、1 和 -1 的三个存储桶(对于 null)?

{
  "size":0,
  "aggregations": {
    "my_boolean": {
      "terms": {
        "field": "my_boolean",
        "missing": -1                 <--- add this
      }
    }
  }
}

它没有必须更改字段类型并将其编码为其他数据类型(整数/字符串)的缺点,并且还使您免于利用脚本,因为这不会很好地扩展。

于 2016-12-23T13:37:11.070 回答
0

最后,我们将各种状态映射到一个字节。

缺失值仅在类型能够具有该值时才有效,因此无论如何我们都需要映射,因此我们在插入期间添加了额外的数字。

true因此,我们不使用带有,false和值的布尔null值,或带有1,2null(缺少 = -1)值的整数,而是使用带有1,2和的字节3,意思是(以随机顺序truefalsenull

于 2017-01-06T16:08:36.793 回答