#100DaysOfMERN - Day 31

Subscribe to my newsletter and never miss my upcoming articles

✏ How to implement a live search function

Yesterday's plan was to code a recipe database, and in fact I've already built 80% of it, but I've decided against blogging about the whole process. Instead I'll pick certain parts and describe those in detail - like a live search function.

The goal: When I fill out the form to add a new recipe to the database, and start typing into the input field to add an ingredient for this recipe, I'm shown a list of ingredients that are already in the database.

The data structure

I have an Ingredient collection in my database, based on this Schema:

const IngredientSchema = new Schema({
    name: {
        type:String,
        required:true,
        unique:true
    }
}, { timestamps: true });

const Ingredient = mongoose.model('ingredient', IngredientSchema);

module.exports = Ingredient;

The Backend

The server has an API endpoint /api/ingredients, which returns a list of all ingredients in the database, using the .find method on the Model:

app.get('/api/ingredients/', (req, res) => {

        Ingredient.find()
            .then(data => res.json(data))
            .catch(err => console.log(err))
})

I'm going to modify this now, to check first if there's a query string attached to the request. For example, if I make a request to /api/ingredients?search=tom, the search string would be available on the req.query object:

req.query // {search: "tom"}

In that case, the .find method should look for possible matches, and only return those. Conveniently, Mongoose allows passing a RegExpression:

app.get('/api/ingredients/', (req, res) => {

    if (req.query.search) {

        const regex = new RegExp(req.query.search, 'g');

        Ingredient.find({ name: regex})
            .then(data => res.json(data))
            .catch(err => console.log(err))

    } else {
        Ingredient.find()
            .then(data => res.json(data))
            .catch(err => console.log(err))
    }
})

The Frontend

When I type more than two characters into the ingredient field, the onChange handler of the input will trigger an axios GET request to the api/ingredients endpoint, with a query string attached:

    function getIngredients(str){
        axios.get(`/api/ingredients?search=${str}`)
            .then(res => {
                const ingredients = res.data.map(e => e.name);
                setIngredients(ingredients);
            })
            .catch(err => console.log(err))
    }

The response will be an array with all matches, which can then be stored in state, ready for React to display. And indeed - typing "tom" into my input field, I'm shown a match: "Tomato" is already in the database 🍅


✏ Recap

I've learned

  • how to implement a live search function using axios and mongoose

✏ Thanks for reading!

I do my best to thoroughly research the things I learn, but if you find any errors or have additions, please leave a comment below, or @ me on Twitter. If you liked this post, I invite you to subsribe to my newsletter. Until next time 👋


✏ Previous Posts

  • Day 1: Introduction, Node.js, Node.js in the terminal
  • Day 2: npm, node_modules, package.json and package-lock.json, local vs global installation of packages
  • Day 3: Create a React app without create-react-app, Webpack, Babel
  • Day 4: npx and cowsay
  • Day 5: npm vs. npx, npm audit, semantic versioning and update rules
  • Day 6: Call stack, event loop, JavaScript engine, JavaScript runtime
  • Day 7: Call stack and event loop in Node.js, setImmediate()
  • Day 8: setImmediate(), process.nextTick(), event loop phases in Node.js
  • Day 9: Network requests with XMLHttpRequest and callbacks
  • Day 10: Promises
  • Day 11: Network requests with XMLHttpRequest and Promises
  • Day 12: React Quiz App part 1
  • Day 13: React Hangman
  • Day 14: FullStackOpen course 1: details of GET and POST requests, request headers
  • Day 15: React Hangman: Trigger fetch with click event callback vs useEffect
  • Day 16: REST API and CRUD
  • Day 17: Boring Book App part 1: React Frontend, Express Backend, GET requests, CORS
  • Day 18: Boring Book App part 2: POST request, File System API
  • Day 19: Boring Book App part 3: Request Parameters, DELETE request
  • Day 20: Boring Book App part 4: PUT request
  • Day 21: Express JS vs Vanilla JS part 1: Server setup, routes
  • Day 22: Express JS vs Vanilla JS part 2: Serve static files with Vanilla Server
  • Day 23: Express JS vs Vanilla JS part 3: Serve static files with Express Server, Middleware
  • Day 24: Express JS: express.Router, Postman
  • Day 25: Express JS: express-handlebars
  • Day 26: MongoDB: Installation, noSQL database structure, Mongo Shell commands
  • Day 27: MongoDB: Project setup, JSON vs BSON, connecting to database, inserting a record
  • Day 28: MongoDB: read and modify data with CRUD operations
  • Day 29: MongoDB with Mongoose: Connecting to the database, Models, Schemas, Saving to the database
  • Day 30: 100DaysOfMERN - App: Backend, Frontend
Rutik Wankhade's photo

Your posts are so insightful. 🙌 It's like a complete roadmap. You have come a long way. I wonder where it will lead at the end of 100 days.

Also, Can you share a few resources you are following?

jsdisco's photo

Thank you! When I started out, 100 days seemed not enough to learn the whole MERN stack, but it's going surprisingly smooth.

My resources-of-choice whenever I want to learn something completely new are these two YT channels, they have almost everything covered:

The Net Ninja

Traversy Media

Other than that, I mostly use the official documentations, or just throw a specific problem into my search engine.

Paolo Urciullo's photo

awesome post!

Catalin Pit's photo

Interesting, I might do something similar!

If you don't mind, what resources are you using to learn?

jsdisco's photo

Apart from The Net Ninja and Traversy Media, I can't really cite any resources that I'd use regularly.

Specifically for the MERN stack though, I can recommend the Full Stack Course from Helsinki University. But the learning curve is steep to say the least, I often get stuck and have to do additional research.

I've also bought the most recent Udemy MERN course from Brad Traversy, but realised I couldn't keep up with the pace - which was the initial motivation for this blog. I think I'm almost ready now to go back to it, though.

And I'd love to read about how others tackle this challenge!