Part 9: Set up the Node.js server to handle Elasticsearch requests
Tags: node, beginners, elasticsearch, javascript
Published: 2022-09-07 15:15:03

[Table of Content](https://dev.to/lisahjung/beginners-guide-to-building-a-full-stack-app-nodejs-react-with-elasticsearch-5347) | [Read Next: Part 10 - Visualize data with Kibana Lens](https://dev.to/lisahjung/part-10-visualize-data-using-kibana-lens-2khe)

###Review
In [part 8](https://dev.to/lisahjung/part-8-build-the-client-side-of-the-app-with-react-2a1b), we have created the client side of the app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/br2qyh91ya6g54cqzsdn.png)

Using the client, the user can search for earthquakes that match the specified criteria(type, magnitude, location, date range). 

We have set up our client to capture the user input and send the input to the server. 

In this blog, we will set up our server to:
- receive the user input from the client and pass the user input into a Elasticsearch request
- send the request to Elasticsearch and receive relevant documents from Elasticsearch
- send the received documents to the client so the search results could be displayed to the user

###Resources

*Would you rather watch a video to learn this content? Click on the link below!*
- [Episode 9: Set up the Node.js server to handle Elasticsearch request](https://www.youtube.com/watch?v=IwBwhb0htII)

*Want the code covered in this blog? Click on the link below to access it!*
- [GitHub repo for part 9](https://github.com/LisaHJung/beginners-guide-to-creating-a-full-stack-Javascript-app-with-Elasticsearch/tree/6-manage_elasticsearch_request) 

### Set up the server to handle Elasticsearch request
*Using your code editor, open the `earthquake_app` directory. Within the `server` directory, locate the `server.js` file.* 

*In `server.js`, replace the existing code with the following code.* 

```javascript
//in server/server.js'
const { Client } = require('@elastic/elasticsearch');
const client = require('./elasticsearch/client');
const express = require('express');
const cors = require('cors');

const app = express();

const data = require('./data_management/retrieve_and_ingest_data');

app.use('/ingest_data', data);

app.use(cors());

app.get('/results', (req, res) => {
  const passedType = req.query.type;
  const passedMag = req.query.mag;
  const passedLocation = req.query.location;
  const passedDateRange = req.query.dateRange;
  const passedSortOption = req.query.sortOption;

  async function sendESRequest() {
    const body = await client.search({
      index: 'earthquakes',
      body: {
        sort: [
          {
            mag: {
              order: passedSortOption,
            },
          },
        ],
        size: 300,
        query: {
          bool: {
            filter: [
              {
                term: { type: passedType },
              },
              {
                range: {
                  mag: {
                    gte: passedMag,
                  },
                },
              },
              {
                match: { place: passedLocation },
              },
              // for those who use prettier, make sure there is no whitespace.
              {
                range: {
                  '@timestamp': {
                    gte: `now-${passedDateRange}d/d`,
                    lt: 'now/d',
                  },
                },
              },
            ],
          },
        },
      },
    });
    res.json(body.hits.hits);
  }
  sendESRequest();
});

const PORT = process.env.PORT || 3001;

app.listen(PORT, () => console.group(`Server started on ${PORT}`));
```
Let's go over the *newly added code*! 

**Heads up!** 

For reference purposes only, I have included screenshots of code that I will be explaining. 

If you need to copy and paste the code, please refer to the code snippet above or the [GitHub repo for part 9](https://github.com/LisaHJung/beginners-guide-to-creating-a-full-stack-Javascript-app-with-Elasticsearch/tree/6-manage_elasticsearch_request).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1spyi58a86b3held13s.png)
  
*Line 4*
We import [cors](https://www.npmjs.com/package/cors) dependency we have installed in [part 2](https://dev.to/lisahjung/part-2-build-a-server-using-nodejs-with-express-52a0). 

We will be using `cors` to allow our server(http://localhost:3000) and client(http://localhost:3001) of different origin to exchange information without encountering a [CORS error](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors).

*Line 12* 
We use `app.use(cors())` to enable all CORS requests. 
 
*Lines 14-66* 
We create an endpoint called `/results` to handle HTTP requests from the client.

###Review from [part 8](https://dev.to/lisahjung/part-8-build-the-client-side-of-the-app-with-react-2a1b)

Using the client, the user can search for earthquakes based on the criteria they select(type, magnitude, location, and date range). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2aiyrgp6erjzrrkohg0h.png)

The user can also sort the results by descending or ascending order of magnitude. 

When the user specifies the criteria and clicks on the search button, the user input is captured and sent to the server.

*Lines 15-19* create constants for the user input received from the client(`type`, `mag`, `location`, `dateRange` and `sortOption`). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ooho9fygebvwpe92klb3.png)

*Lines 21-64* 
We define the `sendESRequest()` function. This function is designed to send a search request to Elasticsearch. 

This search request retrieves earthquake documents that match the user's selected criteria(type, magnitude, location, and time range). 
 
*Line 22*
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1kc0e59liframqq34ow.png)
 
We create a constant called `body` and set it equal to the `client.search()` method. 

Within the `client.search()` method, we leave instructions for Elasticsearch on what documents we wish to retrieve. 

*Line 23* 
We instruct Elasticsearch to search against the index `earthquakes`. 
 
*Line 24*
In the request body(*lines 24-61*), we include the search criteria. 

**Sort by Magnitude** (*Lines 25-31*)
Using the client, a user can sort the search results by descending or ascending order of magnitude. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4qevt1wy0qpgn37jwkxi.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60x12jfoluhiwlzo0f89.png)
  
To accomplish this, we add the `sort` parameter(*line 25*) in the request body. We specify that the search results must be ordered by the value of the field `mag`(*line 27*). 

The sorting order(desc or asc) is determined by the user input `passedSortOption`(*line 28*). 

*Line 32*
We instruct Elasticsearch to retrieve up to 300 matching documents. 
 
*Lines 33-60* 
Our app is designed to retrieve earthquake documents that match the user's chosen criteria(`type`, `mag`, `location`, and `dateRange`). 

The documents must match all four of the user's criteria to be considered as a hit(search result). To retrieve such documents, we will write four queries and combine them into one request. 

The `bool query` becomes super handy when we are trying to accomplish such a task! 

We covered this query in season 1 of Mini Beginner's Crash Course to Elasticsearch and Kibana. Check out these videos([part 1](https://www.youtube.com/watch?v=DhkTerHrXsM) & [part 2](https://www.youtube.com/watch?v=Uh1F2lezIfY)) if you need a refresher!

In a `bool query`(*lines 33-60*), we use a combination of one or more clauses to narrow down our search results. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivpf2wathuojl88pnkfs.png)

In our case, documents in the `earthquakes` index either match or do not match user input(yes or no).  

Therefore, we use the `filter` clause(*line 35*) to retrieve documents that match the user's input of `type`, `magnitude`, `location`, and `date range`.  

**Quake Type** (lines 36-38)
Using our client, a user can select the type of quake from the drop down menu. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ls4by2xobvl4l5akj26r.png)
  
When a user selects an option, the user input is sent to the server and saved as a constant called `passedType`(*line 15*). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0sdptvdx8dbv9b5vfj2.png)

`passedType` contains the option value the user has selected from the dropdown menu(earthquake, quarry blast, ice quake, or explosion).

Since we are looking for a specific `term`(earthquake, quarry blast, ice quake, or explosion) within the document, we use the `term` query. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wki1oj318z410lsmftpr.png)
 
We instruct Elasticsearch to look for the `term` contained in the constant `passedType` in the field `type`(*line 37*). 

**Magnitude** (lines 39-45)
Using our client, a user can select the level of magnitude from the drop down menu. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6wnu085vjfv67o0srfx.png)
 
These options allow the user to search for earthquakes with magnitudes that is greater than or equal to `2.5`, `5.5`, `6.1`, `7`, and `8`. 
 
When a user selects an option, the user input is sent to the server and saved as a constant called `passedMag`(*line 16*). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cb8bbm32yxsq1ev2zd29.png)

`passedMag` contains the value of the chosen option (`2.5`, `5.5`, `6.1`, `7`, or `8`). 

Since we are looking for documents that reflect a range of magnitudes, we use the `range` query for this task. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0yq7ouvmaf5r3b675zj7.png)

We run the range query(*line 40*) on the field `mag`(*line 41*). We look for documents that contain values that are greater than or equal(gte) to the value of `passedMag`(*line 42*). 

**Location** (lines 46-48)
Using our client, a user can type in the location in which they want to search for earthquakes. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ee7uspryn6mmovymtzr8.png)
 
The user input is sent to the server and saved as a constant called `passedLocation`(*line 17*). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oto3j8futl3kwhc1p26d.png)

`passedLocation` contains whatever text the user has typed in. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dd6c9s2oz0vjx5amenlg.png)

To search the field `place` for the typed user input, full text search should be performed. Therefore, we use the `match` query to look for `passedLocation` in the field `place`(*line 47*). 

**Date Range** (lines 50-57)
Using our client, a user can choose the date range of earthquake occurrence.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ax438f75la6iy9ajvuwf.png)
 
This user input is sent to the server and saved as a constant called `passedDateRange`(*line 18*). 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zaoqrqjwgg3fnkio1uog.png)

`passedDateRange` contains the date range option the user has selected(`past 7 days`, `past 14 days`, `past 21 days`, and `past 30 days`). 

Since we are looking for documents that reflect a range of dates, we need to use the `range` query for this task. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqohqapod7q1ctjtz4i6.png)
 
We run the `range` query(*line 51*) on the field `@timestamp`(*line 52*). 

*Lines 54-55*
We instruct Elasticsearch to look for documents whose timestamp falls within the past x days that the user has specified.

At first glance, these lines of code may look complicated so let's break this down.

The term `gte` in *line 53* stands for "greater than or equal to". 

The term `lt` in *line 54* stands for "less than".

We use these terms to specify the date range that a document must fall into to be considered as a search result. 

The term `now/d` represents the current timestamp(the time when your request reaches Elasticsearch). 

Therefore, *lines 54-55* are telling Elasticsearch to find the documents that fall between now and now minus `PassedDateRange` which is the number of days specified by the user. 

As a result, Elasticsearch will look for documents whose timestamp falls within the past x days that the user has specified.

*Line 63*
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5zset7co8vq8r4r4wwz.png)
 
When the request is sent to Elasticsearch, Elasticsearch will retrieve relevant documents and send the documents to the server. 

Once the documents have been received by the server, the server is instructed to send the documents to the client so it can display the search results.

*Line 65*
We call the `sendESRequest()` function so it would execute when the server receives an http request to the `/results` endpoint. 

### Final product
Now the moment we have all been waiting for! Let's check out what we have built! 

*Go back to your terminal.*

*cd into the `earthquake_app` directory. Start the server by executing the following command.*

```javascript
//in terminal within the earthquake_app directory
npm start
```
Screenshot of the terminal:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1r1se1x17jykdvc70ctd.png)

*Add a new tab to your terminal.* 

*cd into the earthquake directory then into the client directory. Start the client by executing the following command.* 

```javascript
//in terminal earthquake_app/client
npm start
```
Screenshot of the terminal:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5o3r42orel5rh32anm1r.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6pl4rgkj7jsuymgendn4.png)

It should automatically display the home page of the app(http://localhost:3000)!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysz97wbvk1mnffjpd3oi.png)

*In the browser, specify the criteria of earthquakes you are looking for and hit the search button.* 

If Elasticsearch contains the documents you seek, you will see the search results displayed in the form of cards. 

You should see that the search results are sorted by the sorting order you have specified!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/518nqvd380gv6fzk0uhx.png)

If Elasticsearch does not have the documents you seek, you will see the following message displayed on the page. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5jue7px2gazhkts7qt0.png)

There you have it! You have successfully created a full stack JavaScript app that can search for earthquake data stored in Elasticsearch!

Next, we are going to explore our data even further.

Move on to [Part 10](https://dev.to/lisahjung/part-10-visualize-data-using-kibana-lens-2khe) to visualize data with Kibana Lens!