"Refining MongoDB queries with a filter after performing a populate

I want to retrieve all records with populated attributes in a query. Here is the TypeScript code:

router.get("/slice", async (req, res) => {
    if (req.query.first && req.query.rowcount) {
        const first: number = parseInt(req.query.first as string);
        const rowcount: number = parseInt(req.query.rowcount as string);
        const question: string = req.query.question as string;
        if (question) {
            let result = await QuestionAnswer.QuestionAnswer.find().populate('question_id').exec();
            let filtered: any[] = [];
            result.forEach((record) => {
                let q = record.get("question_id.question");
                if (q.includes(question))
                    filtered.push(record);
            });
            filtered = filtered.slice(first, first + rowcount);
            res.send(filtered);
        } else {
            let result = await QuestionAnswer.QuestionAnswer.find().skip(first).limit(rowcount).populate('question_id');
            res.send(result);
        }
    } else {
        res.status(404).send();
    }
});

This is the schema used:

const questionSchema = new Schema({
    question: {
        type: String,
        required: true,
    },
    topic_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'topic',
    },
    explanation: {
        type: String,
        required: true,
    },
});

const questionAnswerSchema = new Schema({
    question_id: {
        type: Types.ObjectId,
        required: true,
        ref: 'question',
    },
    answer: {
        type: String,
        required: true,
    },
    isCorrect: {
        type: Boolean,
        required: true,
    },
});

Is there a way to achieve this using find instead of array filtering? I stumbled upon a solution involving aggregation and lookup. Any suggestions?

Answer №1

You can try using regex in the following way:

router.get("/slice", async (req, res) => {
  if (req.query.first && req.query.rowcount) {
    const first: number = parseInt(req.query.first as string);
    const rowcount: number = parseInt(req.query.rowcount as string);
    const question: string = req.query.question as string;

    if (question) {
      const filtered = await QuestionAnswer.QuestionAnswer.find({
        'question_id.question': { $regex: question, $options: 'i' }
      }).populate('question_id').skip(first).limit(rowcount).exec();

      res.send(filtered);
    } else {
      const result = await QuestionAnswer.QuestionAnswer.find()
        .skip(first)
        .limit(rowcount)
        .populate('question_id')
        .exec();

      res.send(result);
    }
  } else {
    res.status(404).send();
  }
});

When specifying options like "i", it enables case insensitive filtering.

Although not tested, this code should function as intended.

Answer №2

Utilizing aggregation allows me to apply filtering using the specific code snippet:

    const filterQuery = {
            'question_id.question': { $regex: question, $options: 'i' },
    };
    QuestionAnswer.QuestionAnswer.aggregate([
        {
            $lookup: {
                from: 'questions',
                localField: 'question_id',
                foreignField: '_id',
                as: 'question',
            },
        },
        {
            $project: {
                _id: 1,
                answer: 1,
                isCorrect: 1,
                question_id: { $arrayElemAt: ['$question', 0] },
            },
        }
    ]).match(filterQuery).exec().then((result) => {
        res.send(result);
    });

Is there a way to calculate the document count without retrieving all records?

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

Tips for implementing collapsible functionality that activates only when a specific row is clicked

I need to update the functionality so that when I click on a row icon, only that specific row collapses and displays its data. Currently, when I click on any row in the table, it expands all rows to display their content. {data.map((dataRow ...

Limit the rate of GET requests

Currently, I am working with an external API that has a rate limit of 25 requests per second. My goal is to take parts of the results and store them in a MongoDB database. I need help figuring out how to effectively rate limit the request function so that ...

Establishing a default value as undefined for a numeric data type in Typescript

I have a question regarding setting initial values and resetting number types in TypeScript. Initially, I had the following code snippet: interface FormPattern { id: string; name: string; email: string; age: number; } const AddUser = () => { ...

Exploring ways to incorporate conditional imports without the need for personalized webpack settings!

Our project is designed to be compatible with both Cordova and Electron, using a single codebase. This means it must import Node APIs and modules specific to Node for Electron, while ignoring them in Cordova. Previously, we relied on a custom webpack con ...

"What is the best way to access and extract data from a nested json file on an

I've been struggling with this issue for weeks, scouring the Internet for a solution without success. How can I extract and display the year name and course name from my .json file? Do I need to link career.id and year.id to display career year cours ...

Retrieve the outermost shell of the VUEjs wrapper test-utils

While working on a VueJS test, I encountered an issue where accessing the outermost layer of HTML seemed impossible. No matter what methods I tried, the outermost layer was always ignored. Is there a way to gain access to this outermost layer so that I c ...

Tips for ensuring a document stays at the top of my collection when performing an update

Whenever I make changes to a document, it always ends up at the bottom of my collection. Is there a way to prevent this from happening? try { await Card.update({_id: fixedUrl}, {$push:{'comments': data}}) } catch (err) { console.log(err ...

Error: The selected module is not a valid top-level option

I am facing an issue while using the babel-loader. I have removed all irrelevant code and just kept the error-related portion. What could be causing this problem? module.exports = merge(baseWebpackConfig, { ... module: { rules: [ ...

Creating a wrapper component to enhance an existing component in Vue - A step-by-step guide

Currently, I am utilizing quasar in one of my projects. The dialog component I am using is becoming redundant in multiple instances, so I am planning to create a dialog wrapper component named my-dialog. my-dialog.vue <template> <q-dialog v-bin ...

Guide to implementing a specified directive value across various tags in Angular Material

As I delve into learning Angular and Material, I have come across a challenge in my project. I noticed that I need to create forms with a consistent appearance. Take for example the registration form's template snippet below: <mat-card> <h2 ...

Error: The program encountered a type error while trying to access the '0' property of an undefined or null reference

I am a beginner in the world of coding and I am currently working on creating an application that allows users to add items to their order. My goal is to have the quantity of an item increase when it is selected multiple times, rather than listing the same ...

What is the best way to update multiple data tables using TypeScript?

In my Angular 7 project, I am utilizing TypeScript to implement two data tables on a single page. Each table requires a rerender method in order to incorporate a search bar functionality. While the data tables come with built-in search bars, the sheer volu ...

Connecting RxJS Observables with HTTP requests in Angular 2 using TypeScript

Currently on the journey of teaching myself Angular2 and TypeScript after enjoying 4 years of working with AngularJS 1.*. It's been challenging, but I know that breakthrough moment is just around the corner. In my practice app, I've created a ser ...

What could be causing the vue-property-decorator @Emit to malfunction in my Vue TypeScript file?

I am currently working with Typescript and Vuejs, where I have a child component called child.component.tsx import Vue from 'vue'; import Component from 'vue-class-component'; import { Emit } from 'vue-property-decorator'; ...

Is there a way to disable the camera on React-QR-Reader after receiving the result?

My experience with react-qr-reader has been smooth for scanning QR codes, however, I'm having trouble closing the camera after it's been opened. The LED indicator of the camera remains on even when not in use. I attempted using the getMedia func ...

The code is running just fine when tested locally, but it seems to encounter an issue when accessed remotely, yielding

Currently, I am in the process of developing a dual twin setup using a Raspberry Pi. The goal is to simulate a continuous transmission of body temperature data, which is then sent to a server that stores the information in a MongoDB database. Everything fu ...

The specified property cannot be found within the type 'JSX.IntrinsicElements'. TS2339

Out of the blue, my TypeScript is throwing an error every time I attempt to use header tags in my TSX files. The error message reads: Property 'h1' does not exist on type 'JSX.IntrinsicElements'. TS2339 It seems to accept all other ta ...

Learn how to directly access your database in an EJS file using Mongoose and Node.js

Is there a way to access the database in my EJS header file? This header is a partial that appears on every page. I have a Category schema and I want to retrieve category names dynamically from the database to display in the header. I tried running the f ...

Storing a byte array in a local file using JavaScript: A Step-by-Step Guide

Recently, I encountered an issue while working with an openssl certificate. Specifically, when I tried to download the certificate from my API, it returned byte arrays that I needed to convert to a PEM file in order to access them through another API. The ...

The isAuthenticated status of the consumer remains unchanged even after being modified by a function within the AuthContext

I am working on updating the signout button in my navigation bar based on the user's authentication status. I am utilizing React Context to manage the isAuthenticated value. The AuthProvider component is wrapped in both layout.tsx and page.tsx (root f ...