Techland - an e-commerce app
Tags: atlashackathon22
Published: 2022-12-08 23:18:52

## What I built

**Techland** is an online e-commerce store where users can list, search and buy computer components.

## Category Submission: Search No More


## App Link
[Techland](https://techland-371020.uc.r.appspot.com)

### Preview

#### Homepage
The homepage consists of featured categories and products.


![Homepage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3613qazu9iau0ttytlr.png)

#### Products Page

Clicking on a category or the Products link on the navigation bar takes you to the products page. It shows all the products or specific products from a selected category and its sub-categories.


![Products Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dg6nfp3vrsbqd91otrpw.png)

#### Individual Product Page

Clicking on a product takes you to the single product page to show details and related products
 

![Product Description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/if33bu4ogrx0jcbbm7uv.png)

#### Search Bar

Clicking the search bar opens a search modal. It can provide real-time auto completions.


![Search Modal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqlj4mvi2o6eh3nbm3uk.png)

Here we can select a suggestion or press <kbd>Enter</kbd> to see the full results.


### Link to Source Code
[Backend](https://github.com/h-sifat/techland-backend)

[Frontend](https://github.com/h-sifat/techland-frontend)

### Permissive License: MIT

## Background

Honestly, this is my first full-stack application and it doesn't do anything extra-ordinary. I've always wanted to build one (for my portfolio) and have been taking few courses on Mongodb University. Finally this hacakthon gave me a the right opportunity to challenge myself and here I'm writing this post at 4:40am in the morning.

### How I built it

This whole app is centered around searching, filtering and fetching product data from the database in the most convenient form. So before we start we need to know about the shape of our products and its category.

#### Product Category Interface

```typescript
interface CategoryInterface {
  _id: string;
  hash: string;
  name: string;
  createdAt: number;
  isDeleted: boolean;
  imageId: string | null;
  parentId: string | null;
  description: string | null;
}
```

#### Product Interface

```typescript
interface ProductImage {
  id: string;
  isMain: boolean;
}

interface ProductBrand {
  id: string;
  name: string;
}

interface CommonProductFields {
  _id: string;
  name: string;
  price: number;
  createdAt: number;
  priceUnit: string;
  categoryId: string;
  brand: ProductBrand;
  description: string;
  images: ProductImage[];
  lastModifiedAt: number;
  shortDescriptions: string[];
  specifications: Record<string, Record<string, string>>;
}
```

#### Full-text search

For full text search I'm using the `name`, `brand.name`, `shortDescriptins` and `description` fields. At first, I was a bit worried about the  `description` field, because it contains **HTML**. But, luckily after reading a lot of documentation I found that I can create a custom text analyzer to strip out all the html before indexing.

#### Auto-completion

For auto-completion I'm only using only the `name` field.

#### Similar Products

I actually didn't know that MongodBD can do this. But I found a search stage called `moreLikeThis` that can compare text based on search index. So, guess what? I've implemented finding similar products without using fancy AI. For this query I've used the `categoryId` and `specifications` field to find similar items.

Here is my atlas search index:

```json
{
  "mappings": {
    "dynamic": false,
    "fields": {
      "brand.name": { "type": "string", "analyzer": "lucene.keyword" },
      "categoryId": { "type": "string", "analyzer": "lucene.keyword" },
      "name": [
        {
          "type": "autocomplete",
          "foldDiacritics": false,
          "tokenization": "edgeGram",
          "analyzer": "lucene.standard"
        },
        { "type": "string", "analyzer": "lucene.standard" }
      ],
      "description": {
        "type": "string",
        "analyzer": "productDescriptionAnalyzer"
      },
      "shortDescriptions": { "type": "string", "analyzer": "lucene.standard" },
      "specifications": { "dynamic": true, "type": "document" }
    }
  },
  "analyzers": [
    {
      "name": "productDescriptionAnalyzer",
      "charFilters": [{ "type": "htmlStrip" }],
      "tokenizer": { "type": "standard" },
      "tokenFilters": [
        { "type": "lowercase" },
        { "type": "snowballStemming", "stemmerName": "english" },
        {
          "type": "stopword",
          "tokens": [
            "a",
            "i",
            "am",
            "an",
            "as",
            "at",
            "be",
            "by",
            "do",
            "he",
            "if",
            "in",
            "is",
            "it",
            "me",
            "no",
            "of",
            "on",
            "or",
            "so",
            "to",
            "up",
            "we",
            "all",
            "and",
            "are",
            "for",
            "has",
            "her",
            "his",
            "off",
            "our",
            "out",
            "the",
            "you",
            "over",
            "that",
            "this",
            "with",
            "your",
            "other"
          ]
        }
      ]
    }
  ]
}
```

#### Finding Products by `categoryId`.

This on was a bit difficult, because categories are hierarchical. Example:

1. Components
   1. MOBO
   1. CPU
   1. RAM
1. Accessories
   1. Keyboard
   1. Mouse
   1. Headphone

So, if I'm listing products form the **Components** category then I should also list all products from its sub-categories. Glad, the `$graphLookup` stage solved the problem.

There is so much that I want to describe but sadly, I don't have much time left. I wanted to make a video explanation but can't do it right now.

I'll try to add some documentation in the `docs` folder of my backend app.

### Tech-stack

#### Backend
 1. Node.js
 1. Express
 1. MongoDb

### Frontend
 1. React

## Conclusion

Lastly, I want to say thanks to the MongodDb team for organizing this beautiful event. I'm especially grateful for the free courses provided by the MongoDb University. I've learned almost everything I know about Mongodb from those courses. Thank you for reading the post 💝.