unable to compare Number data of mongodb in expressJS route

46 Views Asked by At

i am creating a website using nodejs, ejs template, mongodb and express. i am creating a search functionality in my page through forms. but i am facing a small issue.

it has a small logical issue. suppose i have data in which mobile_no is 67890. now i search using mobile_no input and type '67', it give me output that there is no data found. but if i type exact number which is 67890, then it gives me the result. i dont want like this. even if i type the initials then all the data containing number starting with 67 should be shown. i know one solution is to to change type of mobile_no to 'String' instead of 'Number' in my mongoose shcema. but i want it be Number. is it possible to keep it as Number but still get the desired output.

this is my code for job_app_home:

<div class="content-wrapper">
    <section class="content-header">
        <h1>Job Applications</h1>
    </section>
    <% if (noResults) { %>
        <div class="alert alert-warning" role="alert">
            No results found for the given search criteria.
        </div>
    <% } %>    
    <section class="content">
        <div class="row">
            <div class="col-xs-12">
                <div class="box box-default collapsed-box">
                    <div class="box-header with-border">
                        <h3 class="box-title">Advanced Search</h3>
                        <div class="box-tools pull-right">
                            <button class="btn btn-box-tool" data-widget="collapse">
                                <i class="fa fa-search"></i>
                            </button>
                        </div>
                    </div>
                    <div class="box-body">
                        <!-- Include content for advanced search here -->
                        <!-- For example: render a partial -->
                        <%- include ('./job_app_search') %>
                    </div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-12">
                <div class="box">
                    <div class="box-header"></div>
                    <div class="box-body">
                        <table id="example2" class="table table-bordered table-striped">
                            <thead>
                                <tr>
                                    <th>Date</th>
                                    <th>Name</th>
                                    <th>Email</th>
                                    <th>Mobile Number</th>
                                    <th>Job Title</th>
                                    <th>Resume</th>
                                </tr>
                            </thead>
                            <tbody>
                                <% job_applications.forEach(function(b) { %>
                                    <tr>
                                        <td><%= b.createdAt ? b.createdAt.toISOString().slice(0, 10) : '' %></td>
                                        <td><%= b.name %></td>
                                        <td><%= b.email %></td>
                                        <td><%= b.mobile_no %></td>
                                        <td><%= b.job_title %></td>
                                        <td>
                                            <% if (b.resume && b.resume !== '') { %>
                                                <a href="/uploads/<%= b.resume %>" target="_blank">Resume</a>
                                            <% } %>
                                        </td>
                                    </tr>
                                <% }); %>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </section>
</div>

this is my code for job_app_search.ejs:

<form action="/admin/job_applications" method="get">
    <div class="box-body">
      <div class="row">
        <div class="col-md-6">
          <div class="form_group">
            <label>Name</label>
            <div class="field">
              <input type="text" name="name" value="<%= params.name %>" class="form-control"/>
            </div>
          </div>
        </div>
        <div class="col-md-6">
          <div class="form_group">
            <label>Email</label>
            <div class="field">
              <input type="text" name="email" value="<%= params.email %>" class="form-control"/>
            </div>
          </div>
        </div>
        <div class="col-md-6">
          <div class="form_group">
            <label>Mobile</label>
            <div class="field">
              <input type="number" name="mobile_no" value="<%= params.mobile_no %>" class="form-control"/>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-md-12">
      <div class="form-group">
        <div class="box-footer">
          <button type="submit" class="btn btn-primary">Search</button>
        </div>
      </div>
    </div>
  </form>

this is my route code:

router.get('/job_applications', async (req, res) => {
    try {
        let query = {};
        const { name, email, mobile_no } = req.query;
        
        // Check if name is provided in the query
        if (name) {
            query.name = { $regex: name, $options: 'i' }; // Case-insensitive search
        }
        
        // Check if email is provided in the query
        if (email) {
            query.email = { $regex: email, $options: 'i' }; // Case-insensitive search
        }

        // Check if mobile_no is provided and not empty in the query
        if (mobile_no && !isNaN(Number(mobile_no))) {
            query.mobile_no = Number(mobile_no); // Convert to number
        }

        const job_applications = await JobApplication.find(query);
        if (job_applications.length === 0) {
            return res.render('./admin/job_applications/job_app_home', { job_applications, noResults: true, params: req.query });
        }

        res.render('./admin/job_applications/job_app_home', { job_applications, noResults: false, params: req.query });
    } catch (err) {
        console.error(err);
        res.status(500).send('Server Error');
    }
});

this is my shcema:

const mongoose = require('mongoose');

// Define schema for the blogs collection
const blogSchema = new mongoose.Schema({
    title: String,
    seo_name: String,
    blog_type: String,
    author_name: {type: String, default: "Farsaa Group"},
    image: String,
    banner_image: String,
    short_description: String,
    long_description: String,
    publish_date: Date,
    status: { type: Boolean, default: true },
    trending: { type: Boolean, default: true },
    image_content_type: String,
    image_file_size: Number,
    image_updated_at: Date,
    banner_image_content_type: String,
    banner_image_file_size: Number,
    banner_image_updated_at: Date,
}, { timestamps: true });

// Define schema for the contacts collection
const contactSchema = new mongoose.Schema({
    name: String,
    email: String,
    mobile_no: String,
    message: String
}, { timestamps: true });

// Define schema for the job_openings collection
const jobOpeningSchema = new mongoose.Schema({
    title: String,
    status: { type: Boolean, default: true },
    short_description: String,
    long_description: String
}, { timestamps: true });

// Define schema for the users collection
const userSchema = new mongoose.Schema({
    admin: { type: Boolean},
    email: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    reset_password_token: String,
    reset_password_sent_at: Date,
    remember_created_at: Date
}, { timestamps: true });

const jobApplicationSchema = new mongoose.Schema({
    name: {
      type: String,
      required: true
    },
    email: {
      type: String,
      required: true
    },
    mobile_no: {
      type: Number,
      required: true
    },
    resume: {
      type: String, // Assuming you're storing the resume file path
      required: true
    },
    job_title: {
      type: String, // Assuming job_opening_id refers to another document's ObjectId
    //   required: true
    }
    // job_appply_date: {
    //     type: Date,
    //     default: Date.now
    // }
  }, { timestamps: true });
  
  
  // Create models for each schema
const JobApplication = mongoose.model('JobApplication', jobApplicationSchema);
const Blog = mongoose.model('Blog', blogSchema);
const Contact = mongoose.model('Contact', contactSchema);
const JobOpening = mongoose.model('JobOpening', jobOpeningSchema);
const User = mongoose.model('User', userSchema);

module.exports = { Blog, Contact, JobOpening, User, JobApplication };

i have tried a lot of stuff. but it gave different kinds of errors. so i just it kept it like this for now. thanks in advance

1

There are 1 best solutions below

1
jQueeny On

In short you can't do a regex on a property defined as the Number data type.

What you can do is use aggregation to add a field which will be the string equivalent of that Number property and do a regex on that field instead.

It might look something like:

router.get('/job_applications', async (req, res) => {
    try {
        let query = {};
        const { name, email, mobile_no } = req.query;
        
        // Create a pipeline array where we will push each aggregation stage
        const pipeline = [];
        // Create a match object with an $or condition array where will push each regex condition
        const match = { $match: { $or: [ ] } };

        // Check if mobile_no is provided and not empty in the query
        if (mobile_no && !isNaN(Number(mobile_no))) {
            // Stage will add a fields with the string version of the number field
            pipeline.push({
                $addFields: {
                    mobileAsString: {
                        $toString: "$mobile_no"
                    }
                }
            })
            // Do a match on the new string field
            match.$match.$or.push({
                mobileAsString: {
                    $regex: `${mobile_no}`, $options: 'i'
                }
            });
        }
        
        // Check if name is provided in the query
        if (name) {
            match.$match.$or.push({
                name: {
                    $regex: name, $options: 'i'
                }
            })
        }

        // Check if email is provided in the query
        if (email) {
            match.$match.$or.push({
                email: {
                    $regex: email, $options: 'i'
                }
            })
        }
        pipeline.push(match);

        const job_applications = await JobApplication.aggregate(pipeline);

        if (job_applications.length === 0) {
            return res.render('./admin/job_applications/job_app_home', { job_applications, noResults: true, params: req.query });
        }

        res.render('./admin/job_applications/job_app_home', { job_applications, noResults: false, params: req.query });
    } catch (err) {
        console.error(err);
        res.status(500).send('Server Error');
    }
});