乐闻世界logo
搜索文章和话题

Mongoose 如何在搜素时排除某些字段?

5 个月前提问
3 个月前修改
浏览次数64

6个答案

1
2
3
4
5
6

在使用Mongoose进行数据检索时,您可以通过在查询中添加特定的选项来排除某些字段。这是通过在查询的select方法中设置字段为0或者使用-符号排除字段来实现的。以下是几个示例:

示例 1:使用对象字面量排除字段

javascript
// 假设我们有一个User模型 User.find({ /* 查询条件 */ }) .select({ password: 0, __v: 0 }) // 排除password和__v字段 .exec((err, users) => { // 处理结果 });

在这个例子中,我们在select方法中使用一个对象,其中将不想包含的字段设置为0

示例 2:使用字符串排除字段

javascript
User.find({ /* 查询条件 */ }) .select('-password -__v') // 使用字符串,以-开头表示排除字段 .exec((err, users) => { // 处理结果 });

在这个例子中,我们在select方法中使用了一个字符串,字段名前加上-符号表示排除该字段。

示例 3:在查询构造器中直接指定

javascript
User.find({ /* 查询条件 */ }, '-password -__v', (err, users) => { // 处理结果 });

在这个例子中,我们直接在find方法的第二个参数中指定排除的字段。

示例 4:使用projection对象在findOne中排除字段

javascript
User.findOne({ /* 查询条件 */ }, { password: 0, __v: 0 }, (err, user) => { // 处理结果 });

在这个例子中,我们在findOne方法中使用了projection对象来排除某些字段。

示例 5:链式查询中排除字段

javascript
User.find({ /* 查询条件 */ }) .select('-password') .lean() .exec((err, users) => { // 处理结果 });

在这个例子中,我们展示了如何在链式查询中使用select方法排除字段。

这种排除字段的方法是出于性能和安全性的考虑,比如你不希望将密码、用户IDs以及其他敏感信息发送给客户端。

2024年6月29日 12:07 回复

Another way to handle this on the schema level is to override toJSON for the model.

shell
UserSchema.methods.toJSON = function() { var obj = this.toObject() delete obj.passwordHash return obj }

I came across this question looking for a way to exclude password hash from the json i served to the client, and select: false broke my verifyPassword function because it didn't retrieve the value from the database at all.

2024年6月29日 12:07 回复

The documented way is

shell
UserSchema.set('toJSON', { transform: function(doc, ret, options) { delete ret.password; return ret; } });

UPDATE - You might want to use a white list:

shell
UserSchema.set('toJSON', { transform: function(doc, ret, options) { var retJson = { email: ret.email, registered: ret.registered, modified: ret.modified }; return retJson; } });
2024年6月29日 12:07 回复

Come across your question when I was trying to find a similar answer with pymongo. It turns out that in mongo shell, with the find() function call, you can pass a second parameter which specifies how the result document looks like. When you pass a dictionary with attribute's value being 0, you are excluding this field in all the document that come out of this query.

In your case, for example, the query will be like:

shell
db.user.find({an_attr: a_value}, {_creator: 0});

It will exclude _creator parameter for you.

In pymongo, the find() function is pretty much the same. Not sure how it translate to mongoose though. I think it's a better solution compare to manually delete the fields afterwards.

Hope it helps.

2024年6月29日 12:07 回复

I would use the lodash utilities .pick() or .omit()

shell
var _ = require('lodash'); app.post('/example.json', function (req, res) { var user = new User({name: 'John', age: 45, _creator: 'some ObjectId'}); user.save(function (err) { if (err) throw err; // Only get name and age properties var userFiltered = _.pick(user.toObject(), ['name', 'age']); res.json(200, {user: user}); }); });

The other example would be:

shell
var _ = require('lodash'); app.post('/example.json', function (req, res) { var user = new User({name: 'John', age: 45, _creator: 'some ObjectId'}); user.save(function (err) { if (err) throw err; // Remove _creator property var userFiltered = _.omit(user.toObject(), ['_creator']); res.json(200, {user: user}); }); });
2024年6月29日 12:07 回复

You can call toObject() on the document to convert it to a plain JS object that you can freely modify:

shell
user = user.toObject(); delete user._creator; res.json(200, {user: user});
2024年6月29日 12:07 回复

你的答案