The database is unable to perform inclusion on the 'guides' field within the exclusion projection in MongoDB

I encountered an error stating 'Cannot do inclusion on field guides in exclusion projection', which occurred when trying to populate data using pre middleware in my schema:

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

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

The error only occurs when accessing the getAllTour handlers; however, it does not show up when accessing a specified tour.

// The error occurs 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
    }
  });
});
// No error happens here
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
    }
  });
});

You can also view my code at this link

Possible solutions for the errors I am facing

Answer №1

Within the file flux-tours/utils/apiFeatures.js, there is a method where certain fields are excluded by default:

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

Contrastingly, in your flux-tours/models/tourModel.js, the guides field is included using middleware. As per Mongoose's documentation, you cannot have both scenarios simultaneously:

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.

An alternative approach would be to specify the default list of fields explicitly in the else block of the limitFields() function.

Alternatively, you could retrieve the full list of field names using query._fieldsForExec() and then programmatically remove the createdAt _id __v fields:

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

Answer №2

Upon further examination of my code in the previous response, I was able to eliminate the errors by making some minor adjustments to the limitFields() function:

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

By adding this.queryString._fieldsForExec as a parameter, I successfully resolved the issue of encountering undefined values within the .filter method.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason behind an index not being able to cover a query that contains an $or expression?

In my MongoDB 3.2 testing, I explored the behavior of "covered queries" and found that while an $or expression is not covered by an index (at least on the same field), substituting it with an $in expression in the query works perfectly fine. The index use ...

iOS devices are experiencing issues with touchstart and touchend events not functioning when utilizing jquery mobile and cordova

During a previous project, I encountered no problems with the following code snippet. It effectively utilized touchstart and touchend events to adjust the CSS of a button: <script> $('input[type="button"]').on('touchstart', func ...

Guide to building a basic Table View for iOS with the help of HTML, Twitter Bootstrap, jQuery Mobile and more

I have experience with Objective-C, but I am still learning HTML/jQuery/JS. My goal is to create a Table view using these languages. Can anyone provide assistance by guiding me on how to achieve this? I was able to create a static Table view using the co ...

Converting a string value into an object in Javascript using a command that functions similarly to eval in Python

When working with Python, the stringValue variable is often assigned as a string: stringValue = '{"DATA":{"VERSION":1.1, "STATE":True, "STATUS":"ONLINE"}}' To convert this string into a Python di ...

MongoDB-mongoose is not compatible with REST API integration

I'm encountering a peculiar issue with MongoDB-mongoose where it fails to respond to REST API requests. mongoose version - 4.11.3 Mongo DB shell version 3.4.6 Everything is running locally on my computer The connection to Mongo DB is set up as follow ...

How can I compare two fields in a MongoDb query when one of them is an ObjectId?

For my Interactive platform, I have chosen MongoDB as the database. My requirement is that only the blog owner who is signed in should be able to delete the blog. However, there seems to be a loophole where this criteria can be bypassed using another user& ...

Loading an Angular2 app is made possible by ensuring that it is only initiated when a DOM element is detected

In my main.ts file, the code below is functioning perfectly: import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule); H ...

Javascript: A guide on passing an object through multiple nested functions

Hey fellow developers, I'm facing a challenge in my code and seeking advice from the experts out there. I'm attempting to retrieve JSON data from a specific URL, as shown below, and utilize it in a React component outside of the getWeather() fun ...

In the event that the hash consists of just one string, disregard any additional conditional statements

Currently, I am in the process of updating one of my coding playgrounds and facing some issues. If the user has only the "result" string in the hash like this... testhash.html#d81441bc3488494beef1ff548bbff6c2?result I want to display only the result ( ...

Dealing with errors in Vue components: What you need to know

Recently, I encountered an issue where a bug appeared in Chrome but worked fine in Firefox. The problem was with an upload component that looked like this: <input type="file" v-on:change="upload($event)"/> upload(e) { this.name ...

I am encountering difficulty in looping through the data I have received. I have attempted to use forEach, for...of, and map() but have been

Is there a way to log the data (an array of objects) to the console without iterating through it? I understand that the data fetched in a for loop may not have finished executing all the get requests by the time I am using allOrders later, but I am strug ...

Converting a JavaScript function to asynchronous with callback functionality

In the past, I had implemented certain methods in MyClass: MyClass.prototype.method1 = function(data1) { return this.data111.push(data1); }; MyClass.prototype.method2 = function(i) { var data = this.method1(i); if (data.condition1 != null ...

Determine whether one class is a parent class of another class

I'm working with an array of classes (not objects) and I need to add new classes to the array only if a subclass is not already present. However, the current code is unable to achieve this since these are not initialized objects. import {A} from &apo ...

Display the keyboard on IOS when an input field is selected

I'm facing an issue that seems to have no solution. When using input.focus() on IOS, the keyboard doesn't appear searchMobileToggle.addEventListener('click', function() { setTimeout(function(){ searchField.focus(); ...

Uploading multiple images using AngularJS and Spring framework

I'm encountering an issue with uploading multiple images using AngularJS and Spring MVC. While I can successfully retrieve all the files in AngularJS, when I attempt to upload them, no error is displayed, and the process does not reach the Spring cont ...

Can a tiled background be repeated at an angle?

Can a small PNG tile-able pattern image be used to create a background with an angle, such as 20 degrees? Instead of having all the tiles placed next to each other at the same height, can they be arranged along a line? ...

Switching the chosen option in the <select> element repeatedly

I have successfully set the selected value, but now I am wondering how to keep changing it continuously. Initially, my approach was to remove the "selected" attribute from all options and then add it back to the desired option. Surprisingly, this method w ...

Display all images in a dynamic jQuery gallery popup

I am looking to create a dynamic model popup, so I have written the following JavaScript code. However, when I click on a single image, the model popup shows all images' content in a dynamically created div. I want the same image and its content to ap ...

Insufficient module names remaining in NPM

Starting to release modules on NPM has been on my mind, but I can't help but worry about the limited availability of sensible module names in the public domain. Is there a way to create a public NPM module that organizes all my module names within a ...

Tips for querying MongoDB schemas that reference other schemas in the field?

Looking to search for a product by its name within the DOC Schema. However, the products are stored as references in another Product Schema with the _id. Below you can find the code snippets to understand the structure: DOC Schema import mongoose from &qu ...