"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

Setting style based on the condition of the router URL

I am currently facing an issue with a global script in Angular 10 that is supposed to evaluate the current path and apply a style to the navigation bar conditionally. However, it seems to fail at times when using router links. I am wondering if there is a ...

Removing a Request with specified parameters in MongoDB using NodeJS

Working with Angular 4 and MongoDB, I encountered an issue while attempting to send a delete request. My goal was to delete multiple items based on their IDs using the following setup: deleteData(id) { return this.http.delete(this.api, id) } In order ...

Building Reusable Components in Angular 2: A Step-by-Step Guide

I have implemented a feature in my component where a table can be sorted by clicking on the <th></th> tags. When a user clicks on a th tag, the data is sorted either in ascending (ASC) or descending (DESC) order. In my component, I have set up ...

Having trouble resolving the '@angular/material/typings/' error?

I am currently working on tests for an angular project and encountering errors in these two test files: https://pastebin.com/bttxWtQT https://pastebin.com/7VkirsF3 Whenever I run npm test, I receive the following error message https://pastebin.com/ncTg4 ...

What is the process for transforming a string literal type into the keys of a different type?

Imagine having a string literal type like this: type Letters = "a" | "b" | "c" | "d" | "e"; Is there a way to create the following type based on Letters? type LetterFlags = {a: boolean, b: boolean, c: bool ...

Database connection cannot be established

Hello, I am a beginner in the world of coding and currently trying to establish a connection to my server. I encountered an error message: "TypeError: connectDB is not a function" Below is a snippet from my db.js file: const mongoose = requir ...

Limit the types of function parameters to only one option within a union type parameter

I have a collection of tuples that I can use to define variables: type KnownPair = ["dog", "paws"] | ["fish", "scales"]; const goodPair: KnownPair = ["dog", "paws"]; //@ts-expect-error you cannot mix them: const badPair: KnownPair = ["dog", "scales"]; I ...

Having trouble updating values in an array of objects with NodeJS and Mongoose

I'm facing a challenge with updating specific arrays within my UserSchema using the mongoose function findByIdAndUpdate(). Here is my UserSchema: const UserSchema = new mongoose.Schema({ mail: {type: String, required: true, unique: true}, pa ...

The function is not defined for this.X in TypeScript

I am currently developing an application using Angular 6. Within my app, I have the following code snippet: import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: ...

Issue with vue-class-component: encountering TS2339 error when trying to call a method within

My vuejs application is being built using vue-cli-service. After a successful build, I encountered TS2339 errors in my webstorm IDE: Test.vue: <template> <div>{{method()}}</div> </template> <script lang="ts"> impor ...

Encountered a higher number of hooks rendered compared to the previous render error on a component without any conditional hook usage

Within my codebase, I have a component that is responsible for rendering a clickable link to initiate a file upload process. import { gql, useLazyQuery, useMutation } from '@apollo/client'; import { useEffect, useState } from 'react'; i ...

How to implement transactions with MongoDB 4.0 using Callbacks in NodeJs?

Can MongoDB 4.0 transactions be used with mongoose without relying on Promises and instead using Callbacks exclusively? I came across this post but couldn't find information on how to implement Callbacks. Your assistance would be greatly appreciated ...

The distinctions between remove, pull, and unset commands in mongoDB

When it comes to removing a document or an element, the options are remove, pull, and unset. What sets these three methods apart? Which of these is considered the safest approach in today's commanding landscape? And which method is known for being ...

How can we direct the user to another tab in Angular Mat Tab using a child component?

Within my Angular page, I have implemented 4 tabs using mat-tab. Each tab contains a child component that encapsulates smaller components to cater to the specific functionality of that tab. Now, I am faced with the challenge of navigating the user from a ...

Encountering an ERROR with the message "Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError" while attempting to apply a filter to

My mat table includes a filter that utilizes chips to sort by multiple criteria. Upon my initial attempt to filter and save the criteria, I encountered an error called ExpressionChangedAfterItHasBeenCheckedError. The error message indicates a transition f ...

Which is preferable: a single collection with a billion items, or one thousand collections each with one million objects?

What impact can be expected on performance when comparing a single NoSQL database (MongoDB) with one collection - logs - containing 1 billion entries versus a scenario with one thousand collections (logs_source0, logs_source1)? Will there be any differen ...

The element is automatically assigned an 'any' type due to the fact that a 'string' expression cannot be utilized to index the type 'typeof'

I am facing an issue that I am having trouble understanding. The error message reads as follows: TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof The proble ...

Assign a dynamic class to an element within an ngFor iteration

I am working with a template that includes an app-subscriber component being iterated over using *ngFor: <app-subscriber *ngFor="let stream of streams" [stream]="stream" [session]="session" (speakEvents)='onSpeakEvent($event)'> ...

What is the process for importing WebAssembly functions into TypeScript?

I currently have a TypeScript project and am in the process of incorporating a WebAssembly Module to replace certain functionalities. Successfully importing the WebAssembly module involved moving the .wasm loading logic to its own .js file, which is then ...

Adding dependency service to the parent class in Angular

I am working with classes parent and child. The child class is an extension of the parent class. I want to inject the injectable class service into the parent class since all instances of the child class will be using it as well. Can someone guide me on ...