AppDividend
Latest Code Tutorials

Vue Elasticsearch Tutorial With Node.js From Scratch

2,593

Get real time updates directly on you device, subscribe now.

Vue Elasticsearch Tutorial With Node.js From Scratch is today’s leading topic.  We build a frontend in Vue.js and then send a network request to the node.js server and node will query the data to the elastic server. It will get a response and send the JSON response back to the Vue.js client. Now, first, we create a Vue.js frontend and then create a node.js server and index all the data to the elastic-server. Then send a request to the node server and fetch the data. So it is pretty simple stuff to understand. You can find full documentation of elasticsearch here.

# Vue Elasticsearch Tutorial With Node.js

Now let us dive into the programming. First, install Vue.js.

#Step 1: Install Vue.js

We install Vue.js using VueCLI. So if you have not installed Vue CLI, then you can install it using the following command.

npm install -g @vue/cli
# OR
yarn global add @vue/cli

Now create a new Vue.js project using the following command.

vue create vue-elastic

 

Vue Elasticsearch Tutorial With Node.js From Scratch

Go into the project folder.

cd vue-elastic

Start the dev server using the following command.

npm run serve

#Step 2: Create Bootstrap Form For Search.

Now, install the Bootstrap 4 using the following command.

npm install bootstrap --save

# or

yarn add bootstrap

Import the bootstrap 4 file inside src >> main.js file.

// main.js

import Vue from 'vue'
import App from './App.vue'

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')

Okay, replace the existing code by the following code inside App.vue file.

<!-- App.vue -->

<template>
  <div id="app" class="container">
    <div class="input-group input-group-lg bottom">
      <div class="input-group-prepend">
        <span class="input-group-text">Search</span>
      </div>
      <input type="text" class="form-control col-md-6">
    </div>
  </div>
</template>

<script>

export default {
  
}
</script>

<style>
  .bottom {
    margin-top: 50px;
    margin-left: 200px;
  }
</style>

 

Vue Elasticsearch example

Next step is to add the @keydown event to the search area. We need to do this because when the user starts typing in the search box, then we send a network request to the server with the search query and then get a result and display the result. So write the following code inside App.vue file.

// App.vue

<template>
  <div id="app" class="container">
    <div class="input-group input-group-lg bottom">
      <div class="input-group-prepend">
        <span class="input-group-text">Search</span>
      </div>
      <input type="text" 
        class="form-control col-md-6" 
        @keyup.prevent="search"
        v-model="query" />
    </div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      query: ''
    }
  },
  methods: {
    search() {
      console.log(this.query);
      return this.query;
    }
  }
}
</script>

<style>
  .bottom {
    margin-top: 50px;
    margin-left: 200px;
  }
</style>

#Step 3: Install Axios HTTP Promise based library.

Type the following command to install Axios Promise based HTTP library.

npm install axios vue-axios --save

# or

yarn add axios vue-axios

We have not created the node.js server, but we will create in a minute. Bur first, we setup axios to send a network request to the server.

Okay, now add the axios and vue-axios inside the  main.js file.

// main.js

import Vue from 'vue'
import App from './App.vue'
import axios from 'axios';
import VueAxios from 'vue-axios';

import '../node_modules/bootstrap/dist/css/bootstrap.min.css'

Vue.config.productionTip = false

Vue.use(axios, VueAxios);

new Vue({
  render: h => h(App)
}).$mount('#app')

Finally, we can use Axios inside App.vue file.

// App.vue

export default {
  data() {
    return {
      query: '',
      data: []
    }
  },
  methods: {
    search() {
        axios.get("http://localhost:5000/search?q=" + this.query)
              .then(response => {
                console.log(response.data);
                this.data = response.data;
          })
    }
  }
}

So, we will send a network request to the node.js server which is running at port 5000. Right now, it is not running because we have not created yet. So let us create in the next step.

#Step 4: Create node.js web server.

Inside your vue-elastic project, create one folder called server and inside that create one file called server.js.

First, install the following node.js dependencies using the following command.

Related Posts
1 of 15
npm install express body-parser elasticsearch cors --save

Write the following code inside a server.js file.

// server.js

const express = require('express');
const app = express();

const PORT = 5000;

app.listen(PORT, function() {
    console.log('Your node.js server is running on PORT: ',PORT);
});

You can start this node.js server by typing the following command inside server folder.

node server

#Step 5: Install Elasticsearch on the local machine.

If you have already installed Elasticsearch on the mac, then you do not need this step. Otherwise, you can continue with this step. So type the following command to install Elasticsearch via homebrew.

brew install elasticsearch

It will install it and now start the services using the following command.

brew services start elasticsearch

Now, we need to connect our node.js application to the elastic server.

// server.js

const express = require('express');
const app = express();
const elasticsearch = require('elasticsearch');
const fs = require('fs');

const PORT = 5000;

const client = new elasticsearch.Client({
    host: '127.0.0.1:9200',
    log: 'error'
 });

 client.ping({ requestTimeout: 30000 }, function(error) {
    if (error) {
        console.error('elasticsearch cluster is down!');
    } else {
        console.log('Everything is ok');
    }
});

app.listen(PORT, function() {
    console.log('Your node.js server is running on PORT:',PORT);
});

Now, restart the node.js server and see console. You can get like this in the console.

 

Vue Express Elasticsearch example

#Step 6: Create an index and indexing of data.

We need the data to index. So inside server folder, create one file called data.json and add the following code inside it. We will search some of the Game of Thrones main characters.

[
    {
        "cast_name": "Tyrion Lannister",
        "og_name": "Peter Dinklage",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/5/58/Tyrion_main_s7_e6.jpg/revision/latest?cb=20170818050344"
    },
    {
        "cast_name": "Daenerys Targaryen",
        "og_name": "Emilia Clarke",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/5/5f/Daenerys_Dragonpit.jpg/revision/latest?cb=20171015095128"
    },
    {
        "cast_name": "Jon Snow",
        "og_name": "kit Harington",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/a/a5/Profile-JonSnow-707.png/revision/latest?cb=20170828030553"
    },
    {
        "cast_name": "Cersei Lannister",
        "og_name": "Lena Heady",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/c/c3/Profile-CerseiLannister.png/revision/latest?cb=20170828071355"
    },
    {
        "cast_name": "Sansa Stark",
        "og_name": "Sophie Turner",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/7/7e/Sansastark706.jpg/revision/latest/scale-to-width-down/316?cb=20170828072803"
    },
    {
        "cast_name": "Arya Stark",
        "og_name": "Maisie Williams",
        "url": "https://upload.wikimedia.org/wikipedia/en/3/39/Arya_Stark-Maisie_Williams.jpg"
    },
    {
        "cast_name": "Jaime Lannister",
        "og_name": "Nikolaj Coster-Waldau",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/e/eb/Jaime.jpg/revision/latest?cb=20170818052054"
    },
    {
        "cast_name": "Ramsay Bolton",
        "og_name": "Iwan Rheon",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/d/d2/Ramsay_S06E09_RESZIED_FOR_INFOBOX.jpg/revision/latest?cb=20160622071734"
    },
    {
        "cast_name": "Petyr Baelish",
        "og_name": "Aidan Gillen",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/9/9f/Profile-Littlefinger.png/revision/latest?cb=20170826005231"
    },
    {
        "cast_name": "Joffrey Baratheon",
        "og_name": "Jack Gleeson",
        "url": "https://vignette.wikia.nocookie.net/gameofthrones/images/2/25/Joffrey_Season_4_Episode_2_TLATR.jpg/revision/latest?cb=20171105180252"
    }
]

Now, we need to index these data. So let us create another file inside server folder called elasticsearch.js and add the following code in it.

// elasticsearch.js

const elasticsearch = require('elasticsearch');
const fs = require('fs');

const client = new elasticsearch.Client({
    hosts: [ 'http://localhost:9200']
});

client.indices.create({
    index: 'vue-elastic'
}, function(error, response, status) {
    if (error) {
        console.log(error);
    } else {
        console.log("created a new index", response);
    }
});

const bulkIndex = function bulkIndex(index, type, data) {
    let bulkBody = [];
  
    data.forEach(item => {
      bulkBody.push({
        index: {
          _index: index,
          _type: type
        }
      });
      bulkBody.push(item);
    });
  
client.bulk({body: bulkBody})
    .then(response => {
      let errorCount = 0;
      response.items.forEach(item => {
        if (item.index && item.index.error) {
          console.log(++errorCount, item.index.error);
        }
      });
      console.log(
        `Successfully indexed ${data.length - errorCount}
         out of ${data.length} items`
      );
    })
    .catch(console.err);
  };

async function indexData() {
    const articlesRaw = await fs.readFileSync('./data.json');
    const articles = JSON.parse(articlesRaw);
    console.log(`${articles.length} items parsed from data file`);
    bulkIndex('vue-elastic', 'characters_list', articles);
  }

indexData();

Save the file and open the terminal inside the server folder and hit the following command.

node elasticsearch.js

It will index the data. So now our game of thrones characters are ready to query.

#Step 7: Create the query.

Inside the server.js file, add the following code.

// server.js

const express = require('express');
const app = express();
const elasticsearch = require('elasticsearch');
const cors = require('cors');
const bodyParser = require('body-parser');

app.set('port', process.env.PORT || 5000 );
app.use(cors());
app.use(bodyParser.json());

const client = new elasticsearch.Client({
    host: '127.0.0.1:9200',
    log: 'error'
 });

client.ping({ requestTimeout: 30000 }, function(error) {
    if (error) {
        console.error('elasticsearch cluster is down!');
    } else {
        console.log('Everything is ok');
    }
});

app.get('/search', function (req, res){
    
    let body = {
      size: 100,
      from: 0,
      query: {
        match: {
                cast_name: {
                    query: req.query['q'],
                    fuzziness: 4
                }
            }
        }
    }
   
    client.search({index:'vue-elastic', body:body, type:'characters_list'})
    .then(results => {
            res.send(results.hits.hits);
        
    })
    .catch(err=>{
      console.log(err)
      res.send([]);
    });
  
  })

app.listen(app.get('port'), function() {
    console.log('Your node.js server is running on PORT: ',app.get('port'));
});

So, finally when the user tries to search any phrase, it will get this get /search route, and we pass the query parameter.

According to the query, it will find the results and send back to the client.

#Step 8: Display the queried data.

Inside App.vue file, add the following code.

<!-- App.vue -->

<template>
  <div id="app" class="container">
    <div class="input-group input-group-lg bottom">
      <div class="input-group-prepend">
        <span class="input-group-text">Search</span>
      </div>
      <input type="text" 
        class="form-control col-md-6" 
        @keyup.prevent="search"
        v-model="query" />
    </div>
    
    <div  class="card-row">
    <div v-if="data" v-for="(value, index) in data" 
      :key="index"
      :ref="`card_${index}`"
         class="card">
      
      <img class="card-image" :src="value._source.url">
      
      <div class="card-footer">
        <h3 class="card-title">{{value._source.cast_name}}</h3>
        <p class="card-text">by 
          <span class="card-author">{{value._source.og_name}}</span>
        </p>
      </div>
    </div>
  </div>
  </div>
</template>


<script>

export default {
  data() {
    return {
      query: '',
      data: []
    }
  },
  methods: {
    search() {
        this.axios.get('http://localhost:5000/search?q='+this.query)
              .then(response => {
                this.data = response.data;
          })
    }
  }
}
</script>

<style>
body {
  background-color: #E1E7E7;
}

  .bottom {
    margin-top: 50px;
    margin-left: 200px;
  }
.card-row {
  display: flex;
  justify-content: center;
  align-items: center;  
  min-width: 780px;
  width: 100%;
  height: 500px;
}
.card {
  position: relative;
  background-color: #FFFFFF;
  height: 370px;
  width: 240px;
  margin: 10px;
  overflow: hidden;
  box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.5);
}
.card-image {
  position: absolute;
  left: -9999px;
  right: -9999px;
  margin: auto;
  height: 220px;
  min-width: 100%;
}
.card-footer {
  position: absolute;
  bottom: 0;
  height: 130px;
  padding: 10px 15px;
  font-family: Helvetica;
}
.card-text {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.7);
}
.card-title {
  font-family: Serif;
}
.card-author {
  font-size: 14px;
  color: #BAB096;
}
</style>

Finally, we can search the data from Vue.js using elasticsearch.

Vue Elasticsearch Tutorial is over. Thanks for taking.

Github Code

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.