Find() и findOne() в MongoDB, показывающие разные результаты

Вопросы и ответы
Вопрос: У меня есть база данных Mongo, где в коллекции пользователей есть только 1 документ. Я делаю операции find() и findOne() с использованием фильтра имени пользователя. Я получаю неправильный результат операции find(). MongoDB shell version: 3.2.10 connecting to: test Server has startup warnings: 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is

Вопрос:

У меня есть база данных Mongo, где в коллекции пользователей есть только 1 документ. Я делаю операции find() и findOne() с использованием фильтра имени пользователя. Я получаю неправильный результат операции find().

MongoDB shell version: 3.2.10 connecting to: test Server has startup warnings: 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is ‘always’. 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] ** We suggest setting it to ‘never’ 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is ‘always’. 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] ** We suggest setting it to ‘never’ 2016-10-20T20:37:32.681-0700 I CONTROL [initandlisten] > use lab2 switched to db lab2 > db.users.find() { «_id» : ObjectId(«5807ac0765f24dd0660e4332»), «username» : «avtrulzz», «fname» : «Abc», «lname» : «Def», «email» : «test@yahoo.co.in», «password» : «rootuser», «mobile» : NumberLong(1234567890) } > db.users.findOne() { «_id» : ObjectId(«5807ac0765f24dd0660e4332»), «username» : «avtrulzz», «fname» : «Abc», «lname» : «Def», «email» : «test@yahoo.co.in», «password» : «rootuser», «mobile» : NumberLong(1234567890) } > if (db.users.find({username : «noSuchUsername»})) { … print («Username exists»); … } else { … print («User does not exist»); } Username exists > if (db.users.findOne({username : «noSuchUsername»})) { print («Username exists»); } else { print («User does not exist»); } User does not exist > if (db.users.findOne({username : «avtrulzz»})) { print («Username exists»); } else { print («User does not exist»); } Username exists

Смотрите, операция find() возвращает пользователя, который существует, что не соответствует действительности. findOne() ведет себя правильно. enter image description here

Лучший ответ:

Прежде всего, принципиальная разница между findOne() и find():

  • findOne() – если запрос совпадает, возвращается первый документ, в противном случае – ноль.

  • find() – число документов соответствует, курсор возвращается, никогда не ноль.

Поэтому, если поместить в условие if, findOne() может преобразовать в false, если оно не соответствует ни одному документу. Так как find возвращает объект курсора и никогда не возвращает null, он будет преобразован в true, если он помещен в условие if.

find и findOne() возвращают следующее для пустой коллекции:

Ответ №1

Ловушка, в которую вы попадаете, – это довольно недокументированное преобразование из объектов оболочки mongo в boolean в javascript:

findOne() возвращает документ, или nil/null/whatever-it-is-called

find() возвращает курсор, который может быть пустым. Но возвращаемый объект всегда определяется.

Ответ №2

Метод find() возвращает cursor, который всегда truthy, даже если критерии запроса не соответствуют какому-либо документу.

С другой стороны, findOne возвращает первый документ, соответствующий вашим критериям запроса, или null (JavaScript или эквивалент в драйвере вашего языка), если нет документа, соответствующего указанным критериям.

> db.dropDatabase() { «dropped» : «test», «ok» : 1 } > var cursor = db.collection.find(); > cursor; > typeof cursor; object > !cursor; false > var document = db.collection.findOne(); > document; null > typeof document; object > !document; true Ответ №3

Возможно, поиск не является правильным кандидатом для логической проверки, даже если нет данных, он возвращает пустой курсор, который проходит как истинный в булевом

if (db.users.find({username : «noSuchUsername»}).toArray().length>0) { … print («Username exists»); … } else { … print («User does not exist»); }

или

if (db.users.find({username : «noSuchUsername»}).size()>0) { … print («Username exists»); … } else { … print («User does not exist»); }

findOne работает правильно, потому что, если данные не найдены, он возвращает null, который проходит в качестве ложного в логической проверке.

Оцените статью
Добавить комментарий