Hackathon: Building a MongoDB fuzzy search web app with React, Next.js and TailwindCSS

Hackathon: Building a MongoDB fuzzy search web app with React, Next.js and TailwindCSS

ยท

6 min read

Web Development Glossary Search is a web application that I created with the objective of taking part in the MongoDB Atlas Hackathon hosted by the DEV.to community.

The app makes use of several MongoDB features:

  • Search indexing for auto-complete and normal searches using MongoDB Atlas.
  • Serverless functions that are called to perform the actual auto-complete and search features using MongoDB Realm.
  • The capacity to do a fuzzy search, querying the data for the top 10 closest matches to the search term.

In this project, I also implemented a save to favourites functionality using localStorage, and React pagination to browse through the multiple documents returned by MongoDB.

The app was developed using:


๐Ÿ‘‰ Watch it live here: hackathon-mongodb-devto.vercel.app


About the web app

The project is basically a glossary search app. The user can search a web development related term and save it as a favourite.

Application tour

On the start page, the app will present a list with all the terms that are present on the MongoDB database. As there are quite a lot of them, they are paginated.

Once the user starts searching for a particular term, the search field will offer auto-complete options after the third character is entered in the input field. This is accomplished by calling a serverless function on MongoDB Realm.

Serverless function for auto-complete

This is the code for the function:

exports = function (arg) {
    let collection = context.services.get("mongodb-atlas").db("hackathon_db").collection("web_glossary");

    let pipeline = [
        {
            $search: {
                index: "autoCompleteDefinitions",
                "autocomplete": {
                    "query": arg,
                    "path": "title",
                    "tokenOrder": "sequential"
                }
            }
        },
        {
            $limit: 10
        },
        {
            $project: {
                // "_id": 0
                "title": 1
            }
        }];

    return collection.aggregate(pipeline);
};

What this function does is to build a pipeline that searches the auto-complete index (defined in MongoDB Atlas) for query matches, limits those matches to 10, and returns the title of the matching documents. As a result, a dropdown list is shown when the user searches for a term, and the user can select one of them to see its definition:

Drop down

Here is a demo of this functionality in action:

Auto-complete in action

The user can also type a term on the search field and press Enter or click on the Search button. This will call another serverless function defined in MongoDB Realm that will deliver the first 10 matches that are similar to the query sent by the user.

Fuzzy matching

This allows for fuzzy matching terms. For example, the user can enter javoscrpt, and MongoDB will return documents that are a close match to that term, such as JavaScript. This is a really awesome functionality! MongoDB will also return a score indicating how close to the query term is the returned result.

Scores

Here is a demo of this functionality in action:

Fuzzy Search

In case you are wondering, this is the code for this serverless function:

exports = function (arg) {
    let collection = context.services.get("mongodb-atlas").db("hackathon_db").collection("web_glossary");
    let pipeline = [
        {
            '$search': {
                'index': 'searchDefinitions',
                'text': {
                    'query': arg,
                    'path': {
                        'wildcard': '*'
                    },
                    'fuzzy': {}
                }
            }
        },
        {
            $project: {
                title: 1,
                excerpt: 1,
                score: { $meta: "searchScore" }
            }
        },
        {
            $limit: 10
        }
    ];

    return collection.aggregate(pipeline);
};

I wanted to keep this app simple enough to focus on the MongoDB aspect of it, so if you think it's quite bare-bones, that's the reason why. That's also the reason behind the data (the definitions) not being polished enough.


You can take a look at the app source code in my GitHub repository.


Additional Information and Resources

Initial research

Before starting working on this hackathon, I knew one thing: I wanted to implement auto-complete on a search bar because that was something I had never done before. This was the initial stepping stone that pushed me to create a project for the hackathon.

I explored several ideas regarding what the app was going to be all about, ranging from an e-commerce store to hire Hobbits to help around the house, to a database of monsters from Dungeons and Dragons (D&D), and some other cool ideas, but all of them had one fatal flaw: the user should know what to search for. Not many people know by heart the names of Hobbits or D&D demons, so I switched to something more proper for the audience of this hackathon: web development terms.

Doing my research I came across the MDN Glossary of Web-related terms definitions. I found out that I could clone their repository and get all the definitions straight from their GitHub repository, so I did just that!

Data preparation

My goal was to get all the definitions from MDN and transform them into JSON format so I could upload that into a MongoDB collection (a table, in SQL language). Unfortunately, due to the nature of the data, it wasn't an easy task.

The glossary data from MDN is divided into multiple files in markdown format, and I wasn't planning on copying and pasting that by hand. After some online search, I came across the markdown-json package which, after some trial and error, converted all my markdown files into a single JSON file. I did this directly in the console:

npx markdown-json -c ./my-app-settings.json -p */*.md

Once the data was ready, I created a new database and collection on MongoDB and imported the JSON file.

Database and collection

Learning about MongoDB Atlas

I didn't know anything about MongoDB Atlas, so I wanted to know what it was capable of and how I could use it. I found an awesome tutorial by codeSTACKr (who, as far as I know, is working for MongoDB) in which he builds an e-commerce solution using MongoDB Atlas.

After building that app, I had an idea of what I could be doing with my own app. I used React, Next.js, and TailwindCSS to build it, as well as a couple of packages to implement certain functionalities, such as pagination and HTML parsing (the glossary terms extracted from MDN are described using HTML code). I tried to make my app as different from the tutorial as possible so I could actually learn and understand what I was doing. I hope to have accomplished that.

Another great resource for understanding how MongoDB works is its official documentation. This proved to be helpful when I had to modify and delete the collection, because I had to do this using the MongoDB shell.

If you would like a full, detailed, tutorial about how to build this app, please send me a message to my Twitter account.

I hope you enjoyed this post. Hopefully, I managed to inspire you to build your own implementation of the MongoDB features I described earlier.

Cheers!


๐Ÿ—ž๏ธ NEWSLETTER - If you want to hear about my latest articles and interesting software development content, subscribe to my newsletter.

๐Ÿฆ TWITTER - Follow me on Twitter.

Did you find this article valuable?

Support Damian Demasi's Blog by becoming a sponsor. Any amount is appreciated!

ย