2016-12-08 5 views
7

ВыпускКак мы можем иметь дело со значениями NULL, которые имеют определенные значения?

Я пытаюсь сохранить логическое значение 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} 

У этого есть несколько вопросов, один из которых является скоплениями. Там нет , кажется, это простой способ получить значения 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

Другим вариантом является фактически дают нулевой значение, как описано в the manual. Проблема в том, что значение должно быть правильным , и нет ничего, кроме true и false, как логическое.

null_value должен быть тем же самым типом данных, что и поле. Например, длинное поле не может иметь строку null_value.

Это означает, что мы можем использовать другой тип, который поддерживает более 2 значений, , например. integer, но это было бы в моей голове так же, как и высказывание: давайте сопоставляем как целое число и определяем 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». Мы можем назвать их «истинными», «ложными» и «нулевыми» (строк), но это такая же ситуация, но еще больше спрятана.

Вопрос

, что это лучший способ справиться с этими нулевыми проблемами? (Или, может быть, мы должны называть его "тремя состояниями-логическое_выражение проблема?)

Для уточнения: мы боимся, что позже на«нестандартным»значение может вызвать проблемы. Первое, что мы видели, - это bucketing, который мы могли бы исправить с помощью вышеприведенного сценария, но, возможно, мы столкнемся с другими проблемами позже. Поэтому мы ищем наилучшую практику сохранения данных такого типа, а не быстрое решение конкретной проблемы.

+0

Хорошее исследование. В первом варианте вы согласны с тем, что подсчеты истинных/ложных ведер + подсчета недостающего ведра будут правильно суммироваться с общим количеством документов? Если да, то почему вы думаете, что это вызовет проблемы? Я бы посоветовал не создавать скрипты, поскольку он не будет масштабироваться так же, как ваш счетчик документов растет ... Еще один способ может состоять в том, чтобы сортировать «кодировать» три-состояние вашего логического поля в другое поле, чтобы вы могли сохранить чистое логическое поле и использовать это другое поле для выполнения ваших агрегаций. – Val

+0

После рассмотрения некоторых опций о том, как наилучшим образом представлять значения в [трехзначной логике] (https://en.wikipedia.org/wiki/Three-valued_logic), нередко использовать целочисленные значения для хранения трех состояний (мои предпочтения будут равны -1/0/1). – Val

+0

Другой вариант - сохранить поле 'my_boolean' как логическое с двумя значениями (true/false) и иметь второе логическое поле' my_null_boolean', которое будет 'истинным', если' my_boolean' является 'null' и' null', если 'my_boolean' имеет определенные значения, т. е.либо 'true', либо' false' – Val

ответ

0

В конце мы пошли для отображения различных состояний в байты.

Недостающее значение работает только в том случае, если тип способен иметь такое значение, поэтому нам нужно отображение в любом случае, поэтому мы добавляем дополнительный номер при вставке.

Таким образом, вместо булева с true, false и null значениями, или целым числом с 1, 2 и null (с отсутствующим = -1) значениями, мы используем байты с 1, 2 и 3, что означает (в случайном порядке) true, false и null.

3

Вы можете использовать missing setting агрегации terms (т. Е. Не отдельную агрегацию missing).

Таким образом, вы можете продолжать использовать свое логическое поле и получать свои три ведра с 0, 1 и -1 (для нуля)?

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

Он не имеет недостаток, заключающийся в необходимости изменить тип поля и кодирования его в какой-либо другой тип данных (число/строка), а также освобождает вас от привлечения сценариев, так что не очень хорошо масштабируется ,