问题
我正在尝试将布尔值保存到 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
聚合。false
NULL
我知道该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”(字符串),但这是同样的情况,但隐藏得更多。
问题
处理这个空问题的最佳方法是什么? (或者也许我们应该称之为“三态布尔问题”?)
澄清一下:我们担心以后“非标准”值可能会导致问题。我们首先看到的是分桶,我们可能可以使用上面的脚本解决方案来修复它,但也许我们稍后会遇到其他问题。因此,我们正在寻找保存此类数据的最佳实践,而不是针对特定问题的快速解决方案。