0

today I was working on a project that I've, it's made with node.js, express and it uses mongoDB; there I have an input with a search button to look up for users that their name matches with the data input.

I was wondering if there is a way to search just a letter to see every user which they name starts with that particular letter.

Right now I can just search for users that their full name its exactly the same as what the user has written, like if the user name is John, you have to write John or it won't find any match at all.

What I want to achieve, is that if the user puts "jo" as the input, I want to show every user that has "jo" on it's name.

If somebody could clarify this for me it would be really helpful!.

index.js :

const path = require("path");
const MongoClient = require("mongodb").MongoClient;
const bodyParser = require("body-parser");
const crypto = require("crypto");
const jwt = require("jsonwebtoken");

const express = require("express");
const app = express();

require("dotenv").config();

app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: true
  })
);

const port = 8080;

app.listen(port, () => {
  console.log(`Server Runing On Port ${port}`);
});

const mongoKey = process.env.MONGOKEY;
const mongoUsr = process.env.MONGOUSR;
const mongoCluster = process.env.MONGOCLUSTER;

const uri = `mongodb+srv://${mongoUsr}:${mongoKey}@${mongoCluster}`;

const client = new MongoClient(uri, { useNewUrlParser: true });

app.post("/search", (req, res) => {
  const user = req.body.userName;
  client.connect((err, db) => {
    if (err) {
      console.log("cannot connect db" + err);
      return;
    }
    console.log("DataBase connection made successfully");
    const options = {
      sort: "userName"
    };
    const collection = db.db().collection("UserData");
    collection.findOne({ userName: user }, options, (err, doc) => {
      if (err) {
        console.log("cannot make query" + err);
        res.statusMessage = "Cannot Make Query";
        res.statusCode = 400;
        return;
      }
      let document = doc.userName;
      console.log(document);
    });
  });
});

index.html form:

<form
 class="contentForm"
 action="/search"
 method="POST"
 enctype="application/x-www-form-urlencoded"
>
 <h3>Search for Any user here:</h3>
 <div class="searchBox">
   <input type="text" class="searchInput" name="userName" />
   <button type="submit" class="searchButton" />
 </div>
</form>

MongoDb document example:

{"_id":{"$oid":"5e2201a99162aa0344ed4261"},
"userName":"John",
"email":"example@example.io",
"age":"23",
"password":"a01fbfc81d314dfa24329d4197e52f24e6d4116d4a205c6d09edf4dd3809943554e44d02e46a1c6368da2806ff8f0db5eb9beef7d0a0ea763625afab064783de",
"salt":"b787219f672e9d2fe76f1440055bca73"}

Thanks everyone!

F2BEAR
  • 144
  • 1
  • 2
  • 11
  • You can use regex in your find filter – Ayoub Jan 21 '20 at 16:47
  • @Ayoub sorry if it's sounds dumb but what is a find filter and how do you use it? I'm a bit new with mongo – F2BEAR Jan 21 '20 at 16:49
  • 1
    https://www.guru99.com/regular-expressions-mongodb.html – Saurabh Mistry Jan 21 '20 at 16:50
  • Does this answer your question? [How to query MongoDB with "like"?](https://stackoverflow.com/questions/3305561/how-to-query-mongodb-with-like) – whoami - fakeFaceTrueSoul Jan 21 '20 at 16:51
  • @srinivasy in some way it does. However, I don't know if I could use a variable on that. Like, can I use a template literal in there or something? – F2BEAR Jan 21 '20 at 18:39
  • @FacuCarbonel : it takes in regex expressions what do you mean by using template literal, things should work with code, try it.. – whoami - fakeFaceTrueSoul Jan 21 '20 at 18:44
  • @srinivasy I mean, if I use /.*m.*/ would look only for an m, instead of that I want the user to input anything and look if there is any match with that. What I'm trying to say is, how could I use regex taking in mind that I want to use the user input for the search? – F2BEAR Jan 21 '20 at 18:50
  • @srinivasy Let me clarify a bit more. What I want to achieve, using regex or not, is that if the user puts "jo" as the input, I want to show him every user that has "jo" on it's name. – F2BEAR Jan 21 '20 at 19:06
  • @FacuCarbonel : You need to try `var input = /jo/ ; collection.find({userName : input })` – whoami - fakeFaceTrueSoul Jan 21 '20 at 19:58

2 Answers2

0

Well, for those who had the same question as mine, here I left for you the way I solved it. Surely there should be a better way to do it, but this could help so here it is.

The majority of comments on this post suggested to use regex, which I did. But that answer isn't concrete enough for my question, but luckily it cleared a bit the way to get to the answer I needed.

What I wanted was a way to search and print every user in my database which it's name matched with whatever the user inputs for the search. Like if the user searches for "jo" or "lee" or anything else, I want my app to search for any name that matches and print every match found on the console.

What I did is this:

When I called /search in NodeJs at the time I did this question I use to have this query:

collection.findOne({ userName: user }, options, (err, doc) => {
  if (err) {
    console.log("cannot make query" + err);
    res.statusMessage = "Cannot Make Query";
    res.statusCode = 400;
    return;
  }
  let document = doc.userName;
  console.log(document);
});

After some research I changed that to this:

collection.find(
///here I created a regex using a template literal with the variable that holds the input
  { userName: { $regex: `.*${user}.*`, $options: "i" } },  
  { userName: 1 })
/// then I use .forEach because if there was many coincidence I wanted to see all of them
.forEach(doc => {
  let usrName = doc.userName;
  let usrEmail = doc.email;
  let usrAge = doc.age;
///And at the end, I hold every value of the user that I wanted to save on an object called userInfo and I printed it on console.
  let userInfo = {
    usrName,
    usrAge,
    usrEmail
  };
  console.log(userInfo);
});

And that's how I solved it!

F2BEAR
  • 144
  • 1
  • 2
  • 11
0
let name = req.query.name;
name = new RegExp(name, "i");
let query = { userName: name };
collection.find(query).toArray(function(err,docs){
    if(!err)
        return res.send(err);
    res.send(docs);
});

Note: While using a field for search like this, make that field an index. This will make query faster. example: collection.createIndex({"userName":"text"});

vcode
  • 453
  • 4
  • 8