Hackathon: Building a MongoDB fuzzy search web app with React, Next.js and TailwindCSS
Tags: atlashackathon, mongodb, react, webdev
Published: 2022-01-05 10:44:39

### Overview of My Submission

**[Web Development Glossary Search](https://hackathon-mongodb-devto.vercel.app/)** is a web application that I created with the objective of taking part in the [MongoDB Atlas Hackathon](https://dev.to/devteam/announcing-the-mongodb-atlas-hackathon-on-dev-4b6m) 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:
- [React]() for the front end with the following packages:
  - [`realm-web`](https://www.npmjs.com/package/realm-web): for the MongoDB connectivity and Realm access
  - [`html-react-parser`](https://www.npmjs.com/package/html-react-parser): for parsing the data contained in the documents
  - [`react-paginate`](https://github.com/AdeleD/react-paginate): to paginate the documents returned by MongoDB
- [Next.js](https://nextjs.org/) for the back end
- [Heroicons](https://heroicons.com/) for the icons
- [TailwindCSS](https://tailwindcss.com/) for the styling

---

👉 Watch it live here: https://hackathon-mongodb-devto.vercel.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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfe8u14k4kmlnbfjlywz.gif)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puorouc9b6bgyrgpoirf.png)

This is the code for the function:
```javascript
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/426u1r9q8rcazhbpm2tt.png)

Here is a demo of this functionality in action:

![Auto-complete in action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b53368mgpwnb64b3gdap.gif)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kdgn4y8wuxt42s1419u.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4v5ejfct0qxvn9z8181f.png)

Here is a demo of this functionality in action:

<img width="100%" style="width:100%" src="https://media.giphy.com/media/KjPMwLfo9jkVQKqfvF/giphy.gif">

In case you are wondering, this is the code for this serverless function:
```javascript
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.

---

### Submission Category

For my submission, I have chosen the **Choose Your Own Adventure** category, although this app could be easily adapted to an E-commerce solution. 

---

### Link to Source Code

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

{% github https://github.com/Colo-Codes/hackathon-mongodb-devto %}

---

### 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](https://developer.mozilla.org/en-US/docs/Glossary). I found out that I could clone their repository and get all the definitions straight from their [GitHub repository](https://github.com/mdn/content), 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](https://www.npmjs.com/package/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:

```bash
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ds1ci81fzw3vddu7zclp.png)

#### Learning about MongoDB Atlas

<img width="100%" style="width:100%" src="https://media.giphy.com/media/13f5iwTRuiEjjW/giphy.gif">

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](https://www.youtube.com/channel/UCDCHcqyeQgJ-jVSd6VJkbCw) (who, as far as I know, is working for MongoDB) in which he builds an [e-commerce solution using MongoDB Atlas](https://www.youtube.com/playlist?list=PL4RCxklHWZ9v2lcat4oEVGQhZg6r4IQGV).

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](https://docs.mongodb.com/). This proved to be helpful when I had to modify and delete the collection, because I had to do this using the [MongoDB shell](https://docs.mongodb.com/manual/tutorial/remove-documents/).

If you would like a full, detailed, tutorial about how to build this app, please send me a message to my [Twitter](https://twitter.com/DamianDemasi) 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](https://chipper-designer-8106.ck.page/1a819bffe8)._

🐦 **TWITTER -** _Follow me on [Twitter](https://twitter.com/DamianDemasi)._

<a href="https://www.buymeacoffee.com/damiandemasi" target="_blank"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641530738382/Wt_2bHGsXK.png" alt="Buy Me A Coffee" style="height: 40px !important;"></a>