Операторы сравнения MongoDB с нулевым значением

В MongoDB я хотел бы использовать операторы сравнения $gt и $lt, где значение может быть null. Когда операторы не работали с null, я искал документацию, но ничего не нашел. В обоих случаях он не вернул документов (хотя $ne, $gte и $lte вернули документы; это означает, что были документы, которые были как равны, так и не равны null).

Я ожидаю, что $gt будет работать как $ne (как тип null порядок сопоставления Mongo такой низкий) и $lt ничего не возвращает по той же причине.

Я надеялся, что это сработает, поскольку значение, которое я передаю в запрос, является переменной (потенциально null), и я не хочу писать особый случай для null. .

Пример того, что я ожидал, учитывая следующую коллекцию:

{
  id: 1,
  colNum: null
}
{
  id: 2,
  colNum: 72
}
{
  id: 3
}

Я ожидаю следующего запроса:

db.testtable.find( { "colNum" { $gt : null } } )

Вернуться:

{
  id: 2,
  colNum: 72
}

Однако ничего не вернули.

Есть ли причина, по которой $gt и $lt не работают с null, или это ошибка MongoDB, или она действительно должна работать, и, вероятно, это ошибка пользователя?


person TryThis    schedule 23.04.2015    source источник
comment
так в чем твой вопрос?   -  person Salvador Dali    schedule 24.04.2015
comment
Ха! @SalvadorDali хороший момент. Добавлен последний абзац   -  person TryThis    schedule 24.04.2015


Ответы (1)


Подробности

Чтение последнего исходного кода Mongo, в основном есть 2 случая сравнения с участием null:

  1. Если канонические типы BSON сравниваемые элементы различны, только сравнение на равенство (==, >=, <=) null и undefined вернет true; в противном случае любое сравнение с null вернет false.
    Примечание. Никакой другой тип BSON не имеет того же канонического типа, что и null.
  2. Если канонические типы совпадают (т. е. оба элемента равны null), затем compareElementValues вызывается. Для null это просто возвращает разницу между каноническими обоих элементов BSON, а затем выполняет запрошенное сравнение с 0.
    Например, null > null будет преобразовано в (5-5) > 0 --> False, поскольку канонический тип null равен 5.
    Аналогично, null < null будет преобразовано в (5-5) < 0 --> False.

Это означает, что null может быть равно только null или undefined. Любое другое сравнение с участием null всегда будет возвращать false.

Это ошибка?

Обновленный ответ:

Документация по операторам сравнения ($gt, $lt) ссылается на документацию, на которую вы изначально ссылались, что подразумевает, что операторы сравнения должны работать с null. Кроме того, сортировка запросов (т. е., db.find().sort()) действительно точно соответствует задокументированному поведению сравнения/сортировки.

Это как минимум нелогично. Я думаю, что стоит отправить отчет об ошибке на сайт JIRA MongoDB.


Исходный ответ:

Я не думаю, что такое поведение является ошибкой.

общий консенсус для Javascript заключается в том, что undefined означает неназначенный, а null означает назначенный, но в противном случае не определено. Сравнение значений с undefined, кроме равенства, не имеет смысла, по крайней мере, в математическом смысле.

Учитывая, что BSON в значительной степени опирается на JavaScript, это относится и к MongoDB.

person cyfur01    schedule 24.04.2015
comment
Спасибо за подробный ответ. Это было именно то, что я искал. Я не уверен, что полностью согласен с разделом об ошибках. Я понимаю историческую связь с JavaScript, но с тех пор они немного разошлись. Mongo устарел Undefined. Также в документации Mongo я ссылаюсь на вызов Comparison/Sort Order. У кого-нибудь есть мысли по этому поводу? - person TryThis; 24.04.2015
comment
Я пропустил вашу ссылку на документацию. То, что говорится в документации, действительно точно применимо к сортировке (т.е., db.find().sort()), но не к операторам сравнения в запросах (т.е., $gt, $lt, и т. д.). Это, конечно, сбивает с толку. - person cyfur01; 26.04.2015
comment
Обратите внимание, что операторы $lt и $gt в конвейере агрегации действуют иначе, чем $lt и $gt в обычных операторах запроса. В конвейере агрегации undefined значений меньше null. В стандартных запросах это не так. Спасибо Монго. - person Molomby; 21.09.2018