MongoDB Shell NumberInt 类型等于

MongoDB Shell NumberInt type equal

假设我们在 Mongo-Shell 中有两个 NumberInt 类型的对象:

x = NumberInt(100)
y = NumberInt(100)

当我运行下面比较的时候,我想知道为什么最后一个比较是false

x == 100 // True
y == 100 // True
x == y   // False! Why?

不过,我确实希望通过 运行 以下行获得 false

x === y   // False
x === 100 // False
x === 100 // False

符合预期 false。有什么想法吗?

主要原因是相等运算符适用于原始值,但不适用于对象,函数 NumberInt() 正在 mongoshell 中定义对象:

 mongos> x=100
 100
 mongos> typeof x
 number

 mongos> y=NumberInt(100)
 NumberInt(100)
 mongos> typeof y
 object 

比较对象中的值的一个选项是通过 mongoshell 中的 JSON.stringify() 将值展平为字符串,然后进行比较:

 mongos> JSON.stringify(x)===JSON.stringify(y)
 true
 mongos> 

请注意,当您将 NumberInt(100) 对象插入 mongoDB 时,它会被转换为整数,如果您读回它,则它不是对象而是数字类型:

 mongos> db.test.insert({a:y})
 WriteResult({ "nInserted" : 1 })
 mongos> db.test.find()
 { "_id" : ObjectId("6292a16069154745fd5f93c3"), "a" : 100 }
 mongos> db.test.aggregate([  {$project:{aType:{"$type":"$a"  }}} ])
 { "_id" : ObjectId("6292a16069154745fd5f93c3"), "aType" : "int" }
 mongos> var z = db.test.findOne({})
 mongos> typeof z.a
 number
 mongos>

这意味着如果您从 mongoDB 中读取值,您可以毫无问题地与相等运算符进行比较...

我还没有找到确切的答案,但我想下面的大部分答案都是关于这个问题的。要理解,我们可以查看您使用的 ObjectId 实现和比较运算符。

MongoDB Enterprise replset:PRIMARY> o1 = ObjectId("507f1f77bcf86cd799439011")
ObjectId("507f1f77bcf86cd799439011")
MongoDB Enterprise replset:PRIMARY> o2 = ObjectId("507f1f77bcf86cd799439011")
ObjectId("507f1f77bcf86cd799439011")
MongoDB Enterprise replset:PRIMARY> o1.equals(o2)
true
MongoDB Enterprise replset:PRIMARY> o1 == o2  # your case 1
false
MongoDB Enterprise replset:PRIMARY> o1 === o2 # your case 2
false

这种行为的原因是在 equals 实现中,您可以看到是否只写一个没有 () 的方法名称:

MongoDB Enterprise replset:PRIMARY> o1.equals
function(other) {
   return this.str == other.str;
}

请注意,实际比较发生的不是 this(即 ObjectId),而是内部的某个字段:

MongoDB Enterprise replset:PRIMARY> o1.str == o2.str
true

我认为 NumberInt 也会发生类似的情况,只是我还没有找到它。

注意 2,它不会影响正常工作的查询功能:

MongoDB Enterprise replset:PRIMARY> db.coll.insertOne({a : NumberInt(100), b : NumberInt(100)})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("62928aae53867e1d4ea6cee4")
}
MongoDB Enterprise replset:PRIMARY> db.coll.find({ $expr: {$eq: ["$a", "$b"]}})
{ "_id" : ObjectId("62928aae53867e1d4ea6cee4"), "a" : 100, "b" : 100 }