MongoDB:无法在排除投影中包含字段“指南”

问题描述 投票:0回答:1

我收到一些错误,提示“无法在排除投影中包含字段指南”,发生这种情况是因为我尝试在我的架构中使用预中间件来填充数据:

const tourSchema = new mongoose.Schema({
 ...
 guides: [
    {
      type: mongoose.Schema.ObjectId,
      ref: 'User'
    }
  ]
});

tourSchema.pre(/^find/, function(next) {
  this.populate({ path: 'guides' });
  next();
});

但是仅在访问 getAllTour 处理程序时才会发生错误,当仅访问指定的游览时,错误不会显示

// Errors happens here
exports.getAllTours = catchAsync(async (req, res, next) => {
  const features = new APIFeatures(Tour.find(), req.query)
    .filter()
    .sort()
    .limitFields()
    .paginate();
  const tours = await features.query;
  res.status(200).json({
    status: 'success',
    length: tours.length,
    data: {
      tours
    }
  });
});
// But in here there is no error
exports.getTour = catchAsync(async (req, res, next) => {
  const tour = await Tour.findById(req.params.id);
  if (!tour) {
    return next(
      new AppError('No tour found! please check the ID correctly', 404)
    );
  }
  res.status(200).json({
    status: 'success',
    requestedAt: req.requestTime,
    data: {
      tour
    }
  });
});

您还可以在此链接

中查看我的代码

我的错误的解决方案

javascript mongodb error-handling middleware
1个回答
0
投票

flux-tours/utils/apiFeatures.js
中,您可以使用此方法,默认情况下排除某些字段:

limitFields() {
    if (this.queryString.fields) {
      const fields = this.queryString.fields.split(',').join(' ');
      this.query = this.query.select(fields);
    } else {
      this.query = this.query.select('-createdAt _id -__v');
    }
    return this;
}

在您的

flux-tours/models/tourModel.js
中,您使用中间件包含
guides
字段。 根据 Mongoose docs 的说法,你不能两者兼而有之:

A projection must be either inclusive or exclusive. 
In other words, you must either list the fields to include (which excludes all others), 
or list the fields to exclude (which implies all other fields are included). 
The _id field is the only exception because MongoDB includes it by default.

您可以做的是提供默认字段列表,以便在

else
limitFields()
分支中显式选择。

或者,您可以尝试使用

query._fieldsForExec()
获取字段名称的完整列表,然后在代码中删除
createdAt _id __v
字段:

... else {
  const fields = query._fieldsForExec()
                      .filter(f => !['createdAt', '_id', '__v'].includes(f));
  this.query = this.query.select(fields);
}
...

© www.soinside.com 2019 - 2024. All rights reserved.