我正在尝试创建一个将触发预验证中间件的“findOneAndUpdate”查询。
当请求正文中未提供时,需要这些中间件来验证给定坐标并创建“id”字段(是的,不是“_id”字段)。
正如您在下面看到的(请参阅代码中的注释),我很接近,但不明白为什么 mongo
抛出的错误是重复键多样性。
也许 promises 不是去这里的方式,尽管它们让我能够完成比链式 pre
中间件更多的事情。
这是我的 Express 路线:
/* POST /geolocs */
router.post('/', function(req, res, next) {
Geoloc.create(req.body, function(err, post) {
if (err) return next(err);
res.status(201).json(post);
});
});
这是我的架构:
var GeolocSchema = new mongoose.Schema({
id: {
type: String,
required: true,
unique: true
},
location: {
type: {
type: String,
default: 'Point',
required: true
},
coordinates: {
type: [Number],
required: true
}
},
count: Number
});
GeolocSchema.index({
location: '2dsphere'
});
预验证中间件:
// Before validation, check given coordinates for errors.
GeolocSchema.pre('validate', function(next) {
coord = this.location.coordinates
if (this.location.type && coord) {
if (Array.isArray(coord) && coord.length === 2) {
lat = coord[1];
lon = coord[0];
if ((-90 <= lat && lat <= 90) && (-180 <= lat && lat <= 180)) next();
}
}
var err = new Error('...'); // Long error text, irrelevant here
err.status = 400;
next(err);
});
// Then, if no 'id' is given, create it.
GeolocSchema.pre('validate', function(next) {
if (!this.id) {
strLat = this.location.coordinates[1].toFixed(3).replace('.', '_');
strLon = this.location.coordinates[0].toFixed(3).replace('.', '_');
this.id = strLat + '-' + strLon;
}
next();
});
我希望能够做的是在上面的下面添加以下内容:
// Here, using the validate or save hook doesn't change anything.
GeolocSchema.pre('validate', function(next) {
var prom = Geoloc.findOne({
'id': {
$eq: this.id
}
}).exec();
prom.then((err, geoloc) => { // Arrow function here to access 'this'
if (err) next(err);
// If no geoloc was found, go ahead and save.
if (!geoloc) next();
// Else, update to increment the count (THIS WORKS).
return Geoloc.update({'id': this.id}, {$inc: {count: 1}}).exec();
}).then((toto) => {
// This doesn't work, the error thrown by mongo is a duplicate key error (E11000).
if (toto) next(new Error('204'));
else next(new Error("Something that shouldn't happen, happened..."));
});
});
最佳答案
问题是 pre()
和 post()
中间件 save
和 validate
没有被执行通过 update()
、findOneAnUpdate()
等。它在 docs 中提到还有一个 GitHub issue
但是,有 pre('findOneAndUpdate')
和 post('findOneAndUpdate')
Hook 可用(不确定 update
的 Hook 是否可用> 作品)。
希望对你有帮助。
关于node.js - 在预验证中间件之后创建或更新字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41717602/