如何从文档中排除某些字段

IT技术 javascript mongodb express mongoose
2021-02-17 03:21:32

我有以下简单的shema:

 var userSchema = new Schema({
    name : String,
   age: Number,
   _creator: Schema.ObjectId
  });

  var User = mongoose.model('User',userSchema);

我想要做的是创建新文档并返回给客户端,但我想从其中排除“创建者”字段:

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;

      res.json(200, {user: user});     // how to exclude the _creator field?
   });
});

最后,我想发送没有 _creator 字段的新创建的用户:

{
   name: 'John',
   age: 45
} 

是否可以在没有额外查找请求的情况下向mongoose提出请求?

PS:最好通过

6个回答

在架构级别处理此问题的另一种方法是覆盖模型的 toJSON。

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

我遇到了这个问题,正在寻找一种方法来从我提供给客户端的 json 中排除密码哈希,并select: false破坏了我的 verifyPassword 函数,因为它根本没有从数据库中检索值。

有没有办法将其扩展为有条件地过滤字段?例如,管理员希望看到“approved_by”,但普通客户端不应该看到。
2021-04-21 03:21:32
尝试使用 UserSchema.set('toJSON', { transform: function(doc, ret, options) { delete ret.password; return ret; } });
2021-04-29 03:21:32
请注意复制此代码的任何人,obj 之前应该有一个 var 语句,否则会泄漏全局引用。
2021-05-01 03:21:32
不错的解决方案,而不是创建新对象,并且不要设置除 passwordHash 之外的所有字段
2021-05-01 03:21:32
@SirBenBenji 你没有抓住重点。关键是添加一个 toJSON 方法,您可以在其中转换输出。passwordHash属性本身无关
2021-05-05 03:21:32

记录的方式是

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

更新 - 您可能想要使用白名单:

UserSchema.set('toJSON', {
    transform: function(doc, ret, options) {
        var retJson = {
            email: ret.email,
            registered: ret.registered,
            modified: ret.modified
        };
        return retJson;
    }
});
在 v6.0.12 中无法使用 findByIdAndUpdate 或 save 方法。在此处以及 toObject 和 toJson 的文档中尝试过代码。没有错误,但密码字段仍会发送到客户端进行发布和更新。现在,我正在使用自定义对象和 res.json() 在路由器中处理它,直到我弄清楚为什么它在我的架构中不起作用
2021-04-29 03:21:32
使用 findByIdAndUpdate 进行更新时,这在 mongoose v4.4.6^ 中不起作用。请问有什么帮助吗?
2021-05-02 03:21:32
或者,如果你已经有下划线/lodash,你可以使用_.pick UserSchema.set('toJSON', { transform: function(doc, ret, options) { return _.pick(ret, 'email', 'registered', 'modified ') } })
2021-05-08 03:21:32
@xerri - 记录在哪里?我看到 toJSON,但找不到转换
2021-05-13 03:21:32
@xerri -找到它,就糊涂了,因为文档是toObject下没有的toJSON ==> mongoosejs.com/docs/api.html#document_Document-toObject
2021-05-13 03:21:32

当我试图用 pymongo 找到类似的答案时,遇到了你的问题。事实证明,在 mongo shell 中,通过 find() 函数调用,您可以传递第二个参数,该参数指定结果文档的外观。当您传递属性值为 0 的字典时,您将在此查询中出现的所有文档中排除此字段。

例如,在您的情况下,查询将类似于:

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

它将为您排除 _creator 参数。

在 pymongo 中, find() 函数几乎相同。不知道它是如何转化为猫鼬的。我认为与之后手动删除字段相比,这是一个更好的解决方案。

希望能帮助到你。

@nottinhill 多余的撇号!
2021-04-18 03:21:32
绕过 Mongoose 似乎是这些天在 Mongoose 中推荐的做事方式。让我们想知道猫鼬是否能胜任这项任务。
2021-04-29 03:21:32
虽然其他人可能会工作,但这对我来说似乎是正确的答案。为我工作。
2021-05-11 03:21:32
这在某些情况下可能有效,但不是大多数情况下,因为即使您不想显示该字段,您也很有可能希望它在后端进行操作。此解决方案和许多其他类似解决方案的问题在于从未从数据库中检索到相关字段。如果您有其他依赖于它的计算或虚拟字段,它们将无法正确设置。
2021-05-17 03:21:32

我会使用 lodash 实用程序.pick()。忽略()

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});
    });
});

另一个例子是:

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});
    });
});

您可以调用toObject()文档将其转换为可以自由修改的普通 JS 对象:

user = user.toObject();
delete user._creator;
res.json(200, {user: user});
默认情况下,您可以通过包含select: false在字段定义中来隐藏架构字段
2021-05-03 03:21:32
与更改所有对象的默认序列化相比,这是一种更好的方法。
2021-05-03 03:21:32
感谢您的回答,我可以定义一个永远不会在架构级别返回的字段吗?
2021-05-05 03:21:32