How to effectively filter a nested array in a Mongoose pre-find query

I am facing a particular issue. I have comments in my database that can be soft-deleted using a flag is_deleted. When this flag is set to true, it means the comment has been deleted.

The comments are not stored as an independent model; instead, they are nested within another model (simplified model):

let CommentSchema = new Schema({
    text: {
        type: String,
        required: true
    },
    modified_at: {
        type: Date,
        default: null
    },
    created_at: {
        type: Date,
        default: Date.now
    },
    is_deleted: {
        type: Boolean,
        default: false
    },
});

let BookSchema = new Schema({
    ...
    comments: [CommentSchema],
    ...
});

When retrieving all Books with

Books.find({}, (err, books) => {})
, I want to exclude the deleted comments:

BookSchema.pre('find', function() {
    this.aggregate(
    {},
    { $unwind: '$comments'},
    { $match: {'comments.is_deleted': false}})
}); 

However, this does not seem to work. Do you have any suggestions on how to modify the query so that only non-deleted nested comments are returned without having a separate Comment collection?

EDIT: Just to clarify, I am accessing a specific book object through an endpoint like this: /books/{bookId}/comments. It would also be beneficial if this filtering could be applied when fetching all book objects.

Answer №1

If you're looking to filter sub-document elements within a nested array in MongoDB, the positional $ operator is your best bet. Check out this detailed explanation by @Blakes Seven Here

BookSchema.find({
 'comments.is_deleted': false,
}, {
 'comments.$': 1,
});

UPDATE:

While the $ operator only returns one element at a time, refer to this excerpt from the documentation :

The positional $ operator limits the query results to include only the first matching element

You have two options to tackle this issue:

  1. Use an aggregate operation, although it may be slower due to database processing
  2. Retrieve all books and filter their comments using loops

BookSchema.find({
   'comments.is_deleted': false,
}).map(x => Object.assign(x, {
   comments: x.comments.filter(y => !y.is_deleted),
}));

The find method fetches books with non-deleted comments.

The map function iterates over each book.

We then remove any deleted comments before returning the result.

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

Encountering a Module node browserify issue

I recently attempted to utilize the Dyson module node from https://github.com/webpro/dyson#installation. However, upon executing the 'dyson' command, I encountered the following error in my terminal. $ dyson Prueba/ module.js:491 throw err ...

Every time I attempt to access a product from the HomeScreen, I encounter the following issue: "Converting circular structure to JSON"

Whenever I try to click on a product from the HomeScreen.js, it is supposed to take me to the ProductScreen in order to display the detailed information of the product. However, I encountered the following error message: Converting circular structure to J ...

Tips for showcasing checkbox options on an HTML page (utilizing ejs) following the retrieval of information from MongoDB and making it editable for the User

Currently, I store data in mongo for a multiple-choice question and indicate the correct answers. In mongo, I save them like this: question.options.option1.check = "on" for the correct answers. When I navigate to the "edit" page, I retrieve the specific ...

Tips for efficiently handling node-mysql database connections

Hello, I am currently in the process of developing a job recruitment application using NodeJS express framework and utilizing express-handlebars as the Rendering Engine. However, I have encountered an issue where newly posted job listings are not immediate ...

What is the process for creating the token?

I've encountered an issue when generating a token while creating a user account. Despite my efforts, I keep getting an empty set. What could be causing this problem? Could there be an error in the syntax? Take a look at the controller file: import m ...

Issue with Facebook passport/local passport conflict preventing login using Facebook account

Recently, I encountered an issue while trying to implement a login feature using Facebook and passport.js. Although my local login with passport worked smoothly, integrating it with Facebook posed some challenges. My tech stack includes express, mongoose, ...

Guide on how to selectively add middleware such as multer to a fresh express router

For a previous project, I set up a router and utilized multer for handling file uploads. I was able to apply the multer middleware selectively on specific routes as shown below: var router = express.Router(); var multer = require('multer'); var ...

Validator Express: Left-hand Side Brackets

Can LHS Brackets be validated in express-validator for advanced filtering? Here is an example querystring: ?test[gt]=1 I have attempted the following validations: query("test.gt").isAlphanumeric() query("test[gt]").isAlphanumeric() I ...

The parameter value experiences an abrupt and immediate transformation

I recently created an electron app using Node.js and encountered a peculiar issue that I am unable to resolve: Below is the object that I passed as input: { lessons: [ name: "math", scores: [90, 96, 76], isEmpty: false ] } ...

Verify whether a user is marked as an administrator

I need to create a function called isAdmin() that checks if the current user is listed as an admin in the mongodb database. server.js app.get('/api/isadmin', function (req, res) { User.findById(req.user, function (err, user) { if (req.use ...

The process of passing a variable between two routes in an Express application

Is there a method to pass variables between two routes in expressJS without setting it as a global variable? For example, if we have the following routes: exports.routeOne = (req,res) => { var myVariable='this is the variable to be shared'; ...

Struggling to create an API endpoint in express for handling database requests... receiving a 404 error code

I have a specific route set up in my application: app.post('/api/:type/*/*/*', apiRoute.api); Inside my route file, I've implemented the following logic: exports.api = function(req, res) { var type = req.params.type; var entity = ...

Issue: self-signed certificate detected in the certificate chain within Node.js

I'm having trouble installing the nuclide package in atom for my react-native development. I can't figure out why I'm getting the error message below. Can anyone provide some guidance on how to fix this? Thank you in advance. npm ERR! fetc ...

Building interactive chat "hubs" with Node, Express, Heroku, and Socket.io

As I've been working on my app for a while now, scalability issues have started to arise. With my limited experience in Node and Heroku, I'm reaching out for some guidance. Initially, I followed this tutorial to set up my node service, essential ...

"Incorporating the node_modules folder into the Express.js compilation process

Is there a way to automatically include dependencies during Express.js compilation, similar to building a React project? I want to avoid dealing with dependencies after the build process. Any suggestions on how to achieve this? I have not attempted any so ...

The Node.js callback is executed before the entire function has finished executing

const fileSystem = require('fs'); const filePath = require('path'); module.exports.getFiles = function(filepath, callback) { let files = []; fileSystem.exists(filepath, function(exists){ if(exists){ fileSy ...

Find the average value of an array containing objects

Imagine I have an array of objects like this: const BookDetails = [ { bookName: 'Harry Pottar', readingTime: 10663 }, { bookName: 'Harry Pottar', readingTime: 10986 }, { bookName: 'kaptura Tech', readingTime: 7034 } ] I ...

Managing Connection Interruption (Retry) in NodeJS and RethinkDB while Monitoring Table Changes in Real Time

ReqlRuntimeError: Connection is closed in: r.table("users").changes() ^^^^^^^^^^^^^^^^^^^^^^^^^^ at ReqlRuntimeError.ReqlError [as constructor] (/home/user/DEV/express-socketio/node_modules/rethinkdb/errors.js:23:13) at new ReqlRuntimeErr ...

Node.js encountered an SFTP error stating "Error: connect: An existing SFTP connection is already defined."

Working within my node.js application, I have implemented ssh2-sftp-client to upload an image every 5 seconds. The initial upload functions correctly, but upon repeating the process, I encounter an error message: node .\upload.js uploaded screenshot ...

Tips for exploring the array populated with references in Mongoose

Hello, I am delving into MEAN stack development for the first time. Can anyone guide me on how to perform a search in Mongoose populate array? The array contains a reference. Discussion Schema: const discussionSchema = new Schema({ user_id: { type: ...