【问题标题】:find() and findOne() methods in MongoDB showing different resultsMongoDB 中的 find() 和 findOne() 方法显示不同的结果
【发布时间】:2016-10-21 04:33:35
【问题描述】:

我有一个 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() 行为正确。

【问题讨论】:

  • 您是说问题在于前两个查询( find() 与 findOne() )的输出差异,还是最后一个命令的结果( if 块) ?输出结果如何让您认为结果不正确?
  • 我认为 find() 也应该返回“用户不存在”,因为没有名为“noSuchUsername”的用户不存在

标签: mongodb mongodb-query


【解决方案1】:

首先,findOne()find()的基本区别:

  • findOne() - 如果查询匹配,则返回第一个文档,否则返回 null。

  • find() - 无论匹配多少个文档,都会返回一个游标,永远不会为空。

因此,当放入 if 条件时,findOne() 在不匹配任何文档时可以转换为 false。由于find() 返回一个游标对象并且从不返回null,所以在放入if 条件时将转换为true。

findfindOne() 为空集合返回以下内容:

【讨论】:

    【解决方案2】:

    您发现自己陷入的陷阱是在 javascript 中从 mongo shell 对象到布尔值的相当无证的转换:

    findOne() 返回一个文档,或 nil/null/whatever-it-is-call

    find() 返回一个 cursor,可以为空。但是返回的 object 总是被定义的。

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

        【解决方案4】:

        即使没有符合搜索条件的文档,find() 方法也会返回一个数组。一个空数组仍然存在,所以它将作为真。

        findOne() 将只返回一个文档,或者未定义。根据定义,未定义是一个假值。

        如果您知道您将只搜索一个文档,请使用 findOne() 获得更准确的表示。

        【讨论】:

          【解决方案5】:

          也许 find 不是布尔检查的正确候选者,即使没有数据,它也会返回一个空游标,该游标在布尔值中传递为 true

          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,在布尔检查中作为 false 传递。

          【讨论】:

            【解决方案6】:

            如果您使用 find() 方法,请使用 toArray()

            以下2个相同:

            myDoc.findOne()
            myDoc.find().toArray()[0]
            

            【讨论】:

              猜你喜欢
              • 2016-05-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-01
              相关资源
              最近更新 更多