mongoose find()/findOne()查询的结果如何添加额外的属性
温馨提示:这篇文章已超过718天没有更新,请注意相关的内容是否还可用!
在学习 mongoose 的时候,碰到一个需要注意的地方。
给查询结果添加额外的属性时,不能直接在这个结果对象上添加属性。原因和解决方案往下看。
假设 User 集合有一个 name 字段:
const User = new mongoose.Schema({ 'name': String });
(添加一些数据)加上它附带的 _id 字段,应该如下:
> User.find().pretty(); //结果 [ { "_id": ObjectId("62449223fb0988f6c2cecf3d"), "name": 'wffw' }, { "_id": ObjectId("62449223fbca2354d3daf8fca"), "name": 'luyu' }, …… ]
当我查询结果之后,想要添加一个属性给每一个结果时候,神奇的一幕发生了!
User.find().then((list) => { list.map((item, index) => { console.log('1---', item); // (1) item.str = '给item添加一个 str 属性。'; // (2) console.log('2---', item); // (3) }) }) // 结果 1--- [ { "_id": ObjectId("62449223fb0988f6c2cecf3d"), "name": 'wffw' }, …… ] 2--- [ { "_id": ObjectId("62449223fb0988f6c2cecf3d"), "name": 'wffw' }, …… ]
上面 (3) 输出的结果出乎我意料,和 (1) 的结果一模一样,没有发现 str 属性,我的 str 呢?(遇事不决,量子力学?)
这当然不是量子问题。会不会是 这个 item 是只读的,(2)处根本没有赋值成功? 既然如此,那就不直接操作 item ,创建一个新的对象试试(方式一):
User.find().then((list) => { list.map((item, index) => { let one = { _id: item._id, name: item.name, str: '给item添加一个 str 属性。' } console.log('4---', item); // (4) console.log('5---', mylist); // (5) }) }) // 结果 5--- { "_id": ObjectId("62449223fb0988f6c2cecf3d"), "name": 'wffw', "str": '给item添加一个 str 属性。' } // 果然如此呐,哈哈
那么,,,
到这里你以为就结束了? item 真的是只读的吗?事实就是如此的吗?
(真相~ 真香~)
听说过 getOwnPropertyDescriptors() 吧,打印一下 item的属性描述符:
User.find().then((list) => { list.map((item, index) => { item.str = '这是一个新的属性'; console.log('6---', item) // (6) console.log('list[' + index + ']---', Object.getOwnPropertyDescriptors(item)); // (7) }) }) // 结果 //毋庸置疑,(6) 打印的结果里没有 str。
(7) 打印的结果 会是什么呢?如下:
// (7) 打印的结果:取其中一个: list[0]--- { '$__': { value: InternalCache { activePaths: [StateMachine], strictMode: true, skipId: true, selected: {}, fields: {}, exclude: null, _id: new ObjectId("62449223fb0988f6c2cecf3d") }, writable: true, enumerable: true, configurable: true }, '$isNew': { value: false, writable: true, enumerable: true, configurable: true }, _doc: { value: { _id: new ObjectId("62449223fb0988f6c2cecf3d"), name: 'wffw', __v: 0 }, writable: true, enumerable: true, configurable: true }, str: { value: '这是一个新的属性', writable: true, enumerable: true, configurable: true } }
前两个属性("$__"、"
Emm……#?!
现在知道了吧,find().then() 或者 findOne().then() 得到的结果,是有一层封装,在获取这个结果的时候,会自动解封,但是 在自己添加属性的时候,不会自动解封。官方说法:
Mongoose models provide several static helper functions for CRUD operations. Each of these functions returns a mongoose `Query` object.Mongoose模型为CRUD 操作提供了几个静态辅助函数。这些函数中的每一个都返回一个 mongooseQuery对象。
所以,除了(方式一),还有一种方式,赋给 item._doc (方式二) :
User.find().then((list) => { list.map((item, index) => { console.log('8---', item); // (8) item._doc.str = '给item添加一个 str 属性。'; console.log('9---', item); // (9) }) }) // (8) 略 // (9) 结果: 1--- [ { "_id": ObjectId("62449223fb0988f6c2cecf3d"), "name": 'wffw', "str": '给item添加一个 str 属性。' }, …… ]
舒服了。
总结: 方式一 和方式二 都可以,推荐方式一,因为这不需要额外知道"_doc"。
(官网似乎也没有怎么提到_doc,是我菜了)
以上。