Как мы можем иметь дело со значениями NULL, которые имеют определенные значения?
вопрос
Я пытаюсь сохранить логическое значение в asticsearch, но оно имеет значение 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}
У этого есть несколько проблем, одна из которых является агрегацией. Кажется, нет простого способа получить значения true
, false
а также NULL
в совокупности.
missing
функция мне известна, поэтому я знаю, что могу сделать следующее:
GET my_index/_search
{
"size":0,
"aggregations": {
"my_boolean": {
"terms": {
"field": "my_boolean"
}
},
"missing_fields": {
"missing" : {
"field": "my_boolean"
}
}
}
}
Но это приведет к сегменту с 2 значениями (true/false) и отдельным счетчиком для отсутствующих документов. Похоже, это вызовет проблемы.
Вариант 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'. Мы можем назвать их "истинными", "ложными" и "нулевыми" (строками), конечно, но это та же самая ситуация, но скрытая еще больше.
Вопрос
Каков наилучший способ справиться с этой нулевой проблемой? (Или, может быть, мы должны назвать это "tri-state-boolean-problem"?)
Для пояснения: мы опасаемся, что в дальнейшем "нестандартное" значение может вызвать проблемы. Первым, что мы увидели, было объединение, которое мы могли бы исправить с помощью вышеуказанного скриптового решения, но, возможно, позже мы столкнемся с другими проблемами. Поэтому мы ищем лучшую практику сохранения данных такого типа, а не быстрое решение для конкретной проблемы.
2 ответа
В конце мы пошли для отображения различных состояний в байт.
Отсутствующее значение работает только в том случае, если тип может иметь это значение, поэтому в любом случае нам нужно сопоставление, поэтому мы добавляем дополнительное число во время вставки.
Так что вместо логического с true
, false
а также null
значения или целое число с 1
, 2
а также null
(с отсутствующим = -1
) значения, мы используем байт с 1
, 2
а также 3
значение (в случайном порядке) true
, false
а также null
,
Вы могли бы использовать missing
установка terms
агрегация (т.е. не отдельный missing
агрегация).
Таким образом, вы могли бы продолжать использовать свое логическое поле и получить три блока с 0, 1 и -1 (для нуля)?
{
"size":0,
"aggregations": {
"my_boolean": {
"terms": {
"field": "my_boolean",
"missing": -1 <--- add this
}
}
}
}
У него нет недостатка в необходимости изменения типа поля и кодирования его в какой-либо другой тип данных (целое число / строка), а также освобождает вас от использования сценариев, так как это не очень хорошо масштабируется.