【发布时间】:2021-05-27 03:09:45
【问题描述】:
我正在尝试将 req.user._id 与从 MongoDB 查询返回的 ObjectId 数组进行比较。但是所有.includes()、严格和松散的相等检查都失败了。
这是我的控制器中的逻辑(为简单起见被截断):
// Get the ID of the document from the request
const someDocId = req.body.id;
// Perform the search with projection
const result = await Some_DB.findById(someDocId,{adminIds:1, _id:0}).lean();
/*
The structure of the query result is as the following:
{
adminIds: [ 5f77ba7d1a0fba8f5e811e76, 6035f2e7174d4961808944d1 ],
}
And req.user._id is equal to 6035f2e7174d4961808944d1
*/
// When I do
console.log(result.adminIds[1] === req.user._id);
console.log(result.adminIds[1] == req.user._id);
console.log(result.adminIds.includes(req.user._id))
// I also tried
const { ObjectId, } = require('mongoose').Types
console.log(result.adminIds[1] === ObjectId(req.user._id));
console.log(result.adminIds[1] == ObjectId(req.user._id));
console.log(result.adminIds.includes(ObjectId(req.user._id)))
// The result is always false
// Additional Info:
(the results below are the same with or without .lean()
const { ObjectId, } = require('mongoose').Types
const a = sphereInfo.adminIds[1];
const b = req.user._id;
console.log(a instanceof ObjectId); // => true
console.log(b instanceof ObjectId); // => true
console.log(typeof(result.adminIds[1])); // => object
console.log(typeof(req.user._id)); // => object
console.log(result.adminIds[1]);
// 6035f2e7174d4961808944d1 (note:there is no single quote around)
console.log(req.user._id);
// 6035f2e7174d4961808944d1 (note:there is no single quote around)
const a = Object.values(sphereInfo.adminIds[1]);
const b = Object.values(req.user._id);
console.log(a); // => [ 'ObjectID', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
console.log(b); // => [ 'ObjectID', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
const a = Object.getOwnPropertyNames(sphereInfo.adminIds[1]);
const b = Object.getOwnPropertyNames(req.user._id);
console.log(a); // => [ '_bsontype', 'id' ]
console.log(b); // => [ '_bsontype', 'id' ]
console.log(Object.entries(sphereInfo.adminIds[1]));
console.log(Object.entries(req.user._id));
/*
Result:
[
[ '_bsontype', 'ObjectID' ],
[ 'id', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
]
[
[ '_bsontype', 'ObjectID' ],
[ 'id', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
]
*/
console.log(JSON.stringify(sphereInfo.adminIds[1]));
console.log(JSON.stringify(req.user._id));
/*
Result:
"6035f2e7174d4961808944d1"
"6035f2e7174d4961808944d1"
*/
// After removing .lean()
console.log(result.adminIds[1] === req.user._id); // => false
console.log(result.adminIds[1] == req.user._id); // => false
console.log(result.adminIds.includes(req.user._id)) // => true
架构(为简单起见被截断):
// Dependencies
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const SomeSchema = new Schema({
adminIds: [{
type: Schema.Types.ObjectId,
ref: 'user',
}],
}, {
collection: 'SomeCollection',
timestamps: true,
});
module.exports = { SomeSchema, };
无论我怎么看,它们都是完全相同的。但是,所有 .includes()、严格和松散的相等检查都返回 false。更让我困惑的是,无论有没有.lean(),对象结构都是一样的
如果我从查询中删除 .lean(),所有检查仍然失败,只有 .inclides() 返回 true。
根据猫鼬Doc.:
精益选项告诉 Mongoose 跳过对结果文档进行水合。这使得查询更快,内存占用更少,但结果文档是普通的旧 JavaScript 对象 (POJO),而不是 Mongoose 文档。默认情况下,Mongoose 查询返回 Mongoose Document 类的一个实例。文档比普通 JavaScript 对象重得多,因为它们有很多用于更改跟踪的内部状态。启用精益选项会告诉 Mongoose 跳过实例化完整的 Mongoose 文档,而只为您提供 POJO。
文档还提到启用精益的缺点是精益文档没有:
- 更改跟踪
- 铸造和验证
- getter 和 setter
- 虚拟
- 保存()
.lean() 可以影响相等性检查以及.includes() 方法。
所以最后的问题是有人可以向我解释.lean() 是如何导致相等检查失败但.includes 通过的吗?
注意:我不是在问如何比较它们以便检查通过,而是.lean() 如何导致检查失败但 `.includes() 通过。
【问题讨论】:
-
如果您打印两个值,它们是否相同?也打印它们的类型。
-
@MinusFour 我做到了。
console.log(typeof(result.adminIds[1])); // => object console.log(typeof(req.user._id)); // => object -
那么您在帖子中的结果结构具有误导性。这些很可能都是不同的对象,因此相等检查失败的原因。对象的结构是什么?
-
如果您在控制台上获得该输出,那么
lean的文档是在撒谎,或者至少我不会认为它们是 POJO。对两个对象执行Object.entries或JSON.stringify。这将使您了解有关对象结构的更多信息。 -
@MinusFour,我已经用信息编辑了问题。你指定了。
标签: javascript node.js mongodb express mongoose