ساخت یک موتور جستجوی بلادرنگ با Nodejs ،Vuejs و ElasticSearch

elasticsearch-nodejs-vuejs

احتمالاً تا به حال برای تان پیش آمده که سایتی را جستجو کرده و مدت زمان زیادی صبر کرده اید تا نتایج ظاهر شوند. آیا شما به عنوان یک توسعه دهنده تمایل دارید یک موتور جستجوی بلادرنگ برای سایت تان ایجاد کنید؟

در این مقاله قصد داریم یک موتور جستجوی بلادرنگ (همزمان) برای سایت مان ایجاد کنیم تا کاربران پس از جستجو در سایت، بدون رفرش شدن صفحه بتوانند در سریعترین زمان ممکن به نتایج دسترسی داشته باشند.

سرفصل های این آموزش

  1. مقدمه
  2. ایندکس کردن داده ها در ElasticSearch
  3. آموزش ایندکس ها
  4. افزودن مستندات به ایندکس ها
  5. استفاده از Express
  6. آموزش پاسخ های Api جستجو
  7. ایجاد قالب html
  8. انجام جستجو از سمت کلاینت

ElasticSearch یک موتور جستجوی Restful تحلیلی و توزیع شده است که در موارد زیادی قابل استفاده می باشد. ElasticSearch بر اساس Apache Lucene که یک کتابخانه موتور جستجوی متنی با عملکرد بالا است، ساخته شده است.

در این مقاله به شما یاد می دهیم که یک موتور جستجوی بلادرنگ با ElasticSearch ، Node.js، Vue.js بسازید. برای دنبال کردن این آموزش باید کمی با مباحث پایه ای Node.js  و Vue.js آشنایی داشته باشید.

چنانچه تمایل دارید نود جی اس را به صورت مقدماتی تا پیشرفته و پروژه محور یاد بگیرید لطفا روی اینجا کلیک کنید.

علاوه بر این برای آموزش صفر تا صد ویو جی اس نیز می توانید این لینک را دنبال کنید.

ساخت یک موتور جستجوی بلادرنگ با Node، Vue و ElasticSearch

شروع کار

ابتدا باید محیطی که برای این پروژه نیاز داریم را آماده کنیم. چون ما از Node.js استفاده می کنیم، ساده ترین راه این است که یک فولدر جدید ایجاد کرده و دستور npm init را اجرا کنیم.

یک فولدر جدید با نام elastic-code ایجاد کرده و سپس وارد این فولدر شده و دستور npm init را در ترمینال اجرا کنید.

//create a new directory called elastic-node
mkdir elastic-node
//change directory to the new folder created
cd elastic-node
//run npm init to create a package.json file
npm init

دستور بالا یک فایل با نام package.json که برای همه کتابخانه های Node.js مورد نیاز است، ایجاد می کند. سپس باید کتابخانه هایی که برای ساخت موتور جستجوی بلادرنگ مورد نیاز است را نصب می کنیم. این کتابخانه ها عبارتند از:

  • Express: این کتابخانه سرورمان را اجرا می کند.
  • Body-Parser: این کتابخانه با Express کار می کند، و برای تجزیه بدنه درخواست ها استفاده می شود.
  • Elastic Search: این کتابخانه رسمی Node.js برای ElasticSearch است که ما می خواهیم عمل جستجوی بلادرنگ مان را توسط این موتور جستجو انجام دهیم.

برای نصب این کتابخانه ها دستور زیر را اجرا کنید.

npm install express body-parser elasticsearch

حال اولین بخش از محیط کارمان را تنظیم کردیم.

در مرحله بعد باید خود ElasticSearch را هم نصب کنیم. روش های مختلفی برای نصب EasticSearch وجود دارد. در صورتی که از سیستم عامل لینوکس دبیان استفاده میکنی، می توانید فایل .deb را دانلود کرده و با استفاده از دستور dpkg آنرا نصب کنید.

//download the deb package
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.4.deb
//install the deb package using dpkg
sudo dpkg -i elasticsearch-5.6.4.deb

برای نصب روی سایر سیستم عامل ها، به مستندات رسمی ElasticSearch استفاده کنید.

ElasticSearch بعد از نصب به طور خودکار راه اندازی نمی شود و تنها با دستورات زیر راه اندازی و متوقف می شود.

// start the Elasticsearch service
sudo -i service elasticsearch start
// stop the Elasticsearch service
sudo -i service elasticsearch stop

اگر می خواهید ElasticSearch را طوری پیکربندی کنید که به محض بالا آمدن سیستم ، راه اندازی شود، دستور زیر را در ترمینال وارد کنید.

//reload the systemctl daemon
sudo /bin/systemctl daemon-reload
// enable elastic search so it can be called as a service
sudo /bin/systemctl enable elasticsearch.service

بعد از اجرای دستورات بالا، می توانید ElasticSearch را با اجرای دستورات زیر راه اندزای (start) کنید و متوقف کنید.

// start the Elasticsearch service
sudo systemctl start elasticsearch.service
// stop the Elasticsearch service
sudo systemctl stop elasticsearch.service

برای بررسی وضعیت ElasticSearch از دستورات زیر استفاده کنید.

// check status of Elasticsearch
sudo service elasticsearch status

نکته:یکی از ابزارهای عالی برای کار کردن با ElasticSearch افزونه Elastic toolbox گوگل کروم است.این برنامه به شما کمک می کند تا به سرعت ایندکس ها و مستندات تان را مشاهده کنید.

کار با افزونه Elastic toolbox

ایندکس کردن داده ها در ElasticSearch

یک فایل با نام data.js در روت پروژه ایجاد کرده و کدهای زیر را در آن قرار دهید.

//data.js
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
// instantiate an Elasticsearch client
const client = new elasticsearch.Client({
   hosts: [ 'http://localhost:9200']
});
// ping the client to be sure Elasticsearch is up
client.ping({
     requestTimeout: 30000,
 }, function(error) {
 // at this point, eastic search is down, please check your Elasticsearch service
     if (error) {
         console.error('Elasticsearch cluster is down!');
     } else {
         console.log('Everything is ok');
     }
 });

در بالا، ابتدا کتابخانه ElasticSearch را وارد برنامه کرده و سپس یک کلاینت جدید ElasticSearch ایجاد می کنیم و یک آرایه که شامل یک host است را به آن پاس می دهیم.

اگر دقت کنید مقدار host برابر localhost:9200 است. این بدان خاطر است که بطور پیش فرض ElasticSearch روی پورت 9200 کار میکند. سپس یک ping به کلاینت ElasticSearch ارسال کنید تا مطمئن شوید که سرور در حال کار است. اگر دستور node data.js را اجرا کنید، باید یک پیام با عنوان “Every thing is ok” دریافت کنید.

نحوه کار ایندکس ها

بر خلاف پایگاه داده های رایج، ایندکس ElasticSearch یک محل برای ذخیره اسناد مرتبط است. برای مثال، شما می توانید یک ایندکس به نام roxo.ir-tutorials برای ذخیره داده های از نوع cities-list ایجاد کنید.

//data.js
// create a new index called scotch.io-tutorial. If the index has already been created, this function fails safely
client.indices.create({
      index: 'roxo.ir-tutorials'
  }, function(error, response, status) {
      if (error) {
          console.log(error);
      } else {
          console.log("created a new index", response);
      }
});

تکه کد بالا را بعد از متد ping که در مرحله قبل نوشته اید، اضافه کنید.

حال دوباره دستور node data.js را اجرا کنید.

با اینکار باید دو پیام زیر را دریافت کنید:

  • Everything is ok
  • create a new index (with the response from ElasticSearch)

اضافه کردن اسناد به ایندکس ها

توسط Api های ElasticSearch به راحتی می توانید اسناد را به ایندکس هایی که قبلاً ایجاد کرده اید، اضافه کنید. مطابق زیر:

// add a data to the index that has already been created
client.index({
     index: 'roxo.ir-tutorials',
     id: '1',
     type: 'cities_list',
     body: {
         "Key1": "Content for key one",
         "Key2": "Content for key two",
         "key3": "Content for key three",
     }
 }, function(err, resp, status) {
     console.log(resp);
 });

در کد بالا، Body همان سندی است که می خواهیم به ایندکس roxo.ir-tutorials اضافه کنیم. به خاطر داشته باشید که اگر در بالا به کلید id مقداری نسبت ندهید، ElasticSearch یک مقدار به صورت خودکار برای آن تولید می کند.

در این آموزش، سندمان شامل لیستی از تمام شهرهای جهان است. اگر بخواهید هر شهر را یکی یکی وارد کنید، ممکن است روزها یا هفته ها طول بکشد تا تمام آنها را ایندکس کنید. خوشبختانه ElasticSearch یک متد به نام bulk دارد که برای کار با حجم زیاد اطلاعات استفاده می شود.

ابتدا فایل json که تمام شهرهای جهان در آن قرار گرفته را از اینجا دانلود کرده و از حالت فشرده خارج کنید، سپس فایل cities.json را در روت پروژه ذخیره کنید.

در مرحله بعد با استفاده از Api ای که برای ورود دسته جمعی اطلاعات است (bulk) تمام آن اطلاعات را وارد ایندکس می کنیم.

//data.js
// require the array of cities that was downloaded
const cities = require('./cities.json');
// declare an empty array called bulk
var bulk = [];
//loop through each city and create and push two objects into the array in each loop
//first object sends the index and type you will be saving the data as
//second object is the data you want to index
cities.forEach(city =>{
   bulk.push({index:{ 
                 _index:"scotch.io-tutorial", 
                 _type:"cities_list",
             }          
         })
  bulk.push(city)
})
//perform bulk indexing of the data passed
client.bulk({body:bulk}, function( err, response  ){ 
         if( err ){ 
             console.log("Failed Bulk operation".red, err) 
         } else { 
             console.log("Successfully imported %s".green, cities.length); 
         } 
});

در بالا با یک حلقه تکرار تمام شهرها را از فایل json گرفته و آنها را به ایندکس افزوده و یک نوع (type) را هم به آن اضافه می کند.

اگر دقت کنید می بینید که ما دوبار از push در آرایه استفاده کردیم.

اینکار به این خاطر است که apiی bulk انتظار دارد یک آبجکت شامل تعریف ایندکس در ابتدا، و سپس سندی که می خواهید ایندکس کنید را به عنوان پارامتر دوم دریافت کند.

برای کسب اطلاع بیشتر می توانید اینجا را بررسی کنید.

سپس متد client.bulk را تعریف کردیم و یک آرایه bulk جدید به متد پاس میدهیم. با اینکار تمام داده های تان با ایندکس roxo.ir-tutorials و از نوع cities_list در ElasticSearch ایندکس می شود.

استفاده از Express

نمونه instance  ElasticSearch آماده بکار است. و می توانید با Node.js به آن متصل شوید. حال می خواهیم با استفاده از Express یک صفحه فرود (landing page) طراحی کنیم. برای اینکار یک فایل با نام index.js ایجاد کرده و کدهای زیر را به آن اضافه کنید.

//index.js
//require the Elasticsearch librray
const elasticsearch = require('elasticsearch');
// instantiate an elasticsearch client
const client = new elasticsearch.Client({
   hosts: [ 'http://localhost:9200']
});
//require Express
const express = require( 'express' );
// instanciate an instance of express and hold the value in a constant called app
const app     = express();
//require the body-parser library. will be used for parsing body requests
const bodyParser = require('body-parser')
//require the path library
const path    = require( 'path' );

// ping the client to be sure Elasticsearch is up
client.ping({
     requestTimeout: 30000,
 }, function(error) {
 // at this point, eastic search is down, please check your Elasticsearch service
     if (error) {
         console.error('elasticsearch cluster is down!');
     } else {
         console.log('Everything is ok');
     }
 });


// use the bodyparser as a middleware  
app.use(bodyParser.json())
// set port for the app to listen on
app.set( 'port', process.env.PORT || 3001 );
// set path to serve static files
app.use( express.static( path.join( __dirname, 'public' )));
// enable CORS 
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

// defined the base route and return with an HTML file called tempate.html
app.get('/', function(req, res){
  res.sendFile('template.html', {
     root: path.join( __dirname, 'views' )
   });
})

// define the /search route that should return elastic search results 
app.get('/search', function (req, res){
  // declare the query object to search elastic search and return only 200 results from the first result found. 
  // also match any data where the name is like the query string sent in
  let body = {
    size: 200,
    from: 0, 
    query: {
      match: {
          name: req.query['q']
      }
    }
  }
  // perform the actual search passing in the index, the search query and the type
  client.search({index:'scotch.io-tutorial',  body:body, type:'cities_list'})
  .then(results => {
    res.send(results.hits.hits);
  })
  .catch(err=>{
    console.log(err)
    res.send([]);
  });

})
// listen on the specified port
app .listen( app.get( 'port' ), function(){
  console.log( 'Express server listening on port ' + app.get( 'port' ));
} );

تشریح کد بالا

  • وارد کردن (Require) کتابخانه ها,body-parser,Path Express
  • ایجاد یک نمونه جدید Express و نسبت دادن آن به ثابت app
  • استفاده از middleware bodyParser
  • قرار دادن بخش استاتیک برنامه به یک فولدر با نام public
  • تعریف یک middleware که هدر cors را به برنامه اضافه می کند.
  • تعریف روت Get برای آدرس root برنامه که توسط / نشان داده می شود. در اینجا من یک فایل با نام html که در فولدر views قرار دارد را بر می گردانم.

بدنه جستجو به جز query می تواند شامل پروپرتی های اختیاری دیگری هم باشد، مثل size و from.

پروپرتی size تعداد اسنادی که در پاسخ جستجو ارسال می شود را مشخص می کند. اگر هیچ مقداری را بر نگرداند، بطور پیش فرض 10 صفحه برگشت داده می شود.

پروپرتی from ایندکس شروع اسناد برگشت داده شده را مشخص می کند. این پروپرتی ها برای صفحه بندی کاربرد دارند.

آموزش پاسخ های API جستجو

اگر بخواهید پاسخ ها را از API جستجو خارج کنید به اطلاعات زیادی برخورد خواهید کرد.

{ took: 88,
timed_out: false,
_shards: { total: 5, successful: 5, failed: 0 },
hits:
{ total: 59,
 max_score: 5.9437823,
 hits:
  [ {"_index":"scotch.io-tutorial",
  "_type":"cities_list",
  "_id":"AV-xjywQx9urn0C4pSPv",
  "_score":5.9437823,"
  _source":{"country":"ES","name":"A Coruña","lat":"43.37135","lng":"-8.396"}},
    [Object],
...
    [Object] ] } }

در بالا، پروپرتی took تعداد میلی ثانیه هایی است که برای پیدا کردن جواب صرف شده است.

time_out وقتی true می شود که هیچ نتیجه ای یافت نشود، _shards برای اطلاع درباره وضعیت نودهای مختلف استفاده می شود .و در نهایت hits شامل نتایج جستجو است.

داخل پروپرتی hits یک آبجکت با پروپرتی های زیر را داریم:

total: تعداد کل آیتم های مطابقت داده شده است.

max_score: بیشترین امتیاز آیتم های یافت شده.

hits: یک آرایه شامل آیتم های یافت شده است.

ساخت قالب html

ابتدا دو فولدر به نام های Views و public در روت پروژه ایجاد کنید. سپس یک فایل با نام template.html در فولدر views ایجاد کرده و کدهای زیر را در آن قرار دهید.

<!-- template.html -->
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div class="container" id="app">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>Search Cities around the world</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <form action="" class="search-form">
                <div class="form-group has-feedback">
                    <label for="search" class="sr-only">Search</label>
                    <input type="text" class="form-control" name="search" id="search" placeholder="search" v-model="query" >
                    <span class="glyphicon glyphicon-search form-control-feedback"></span>
                </div>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3" v-for="result in results">
            <div class="panel panel-default">
                <div class="panel-heading">
                <!-- display the city name and country  -->
                    {{ result._source.name }}, {{ result._source.country }} 
                </div>
                <div class="panel-body">
                <!-- display the latitude and longitude of the city  -->
                    <p>lat:{{ result._source.lat }}, long: {{ result._source.lng }}.</p>
                </div>
            </div>
        </div>
    </div>
</div>
<!--- some styling for the page -->
<style>
    .search-form .form-group {
        float: right !important;
        transition: all 0.35s, border-radius 0s;
        width: 32px;
        height: 32px;
        background-color: #fff;
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
        border-radius: 25px;
        border: 1px solid #ccc;
    }

    .search-form .form-group input.form-control {
        padding-right: 20px;
        border: 0 none;
        background: transparent;
        box-shadow: none;
        display: block;
    }

    .search-form .form-group input.form-control::-webkit-input-placeholder {
        display: none;
    }

    .search-form .form-group input.form-control:-moz-placeholder {
        /* Firefox 18- */
        display: none;
    }

    .search-form .form-group input.form-control::-moz-placeholder {
        /* Firefox 19+ */
        display: none;
    }

    .search-form .form-group input.form-control:-ms-input-placeholder {
        display: none;
    }

    .search-form .form-group:hover,
    .search-form .form-group.hover {
        width: 100%;
        border-radius: 4px 25px 25px 4px;
    }

    .search-form .form-group span.form-control-feedback {
        position: absolute;
        top: -1px;
        right: -2px;
        z-index: 2;
        display: block;
        width: 34px;
        height: 34px;
        line-height: 34px;
        text-align: center;
        color: #3596e0;
        left: initial;
        font-size: 14px;
    }
</style>

در کد های بالا دو قسمت اصلی وجود دارد:

کدهای html : در این قسمت سه کتابخانه را وارد صفحه می کنیم.

1- فایل css بوت استرپ، برای استایل دهی صفحه

2- Axios.js : برای ساخت درخواست های http به سرور

3- Vue.js: یک فریم ورک سبک برای طراحی ظاهر برنامه

کدهای css: در اینجا کدی نوشتیم تا هنگامی که ماوس را به سمت فیلد جستجو ببرید، آن فیلد ظاهر شده و در صورت دور شدن از آن، پنهان می شود.

در مرحله بعد، یک input برای جستجو داریم که v-model آن را به query نسبت می دهیم. سپس با یک حلقه تکرار تمام نتایج جستجو را می گیریم.

حال دستور node index.js را اجرا کرده و به آدرس localhost:3001 مراجعه کنید. نتیجه مطابق تصویر زیر است:

سپس یک تگ script به فایل template.html اضافه می کنیم.

//template.html
// create a new Vue instance
var app = new Vue({
    el: '#app',
    // declare the data for the component (An array that houses the results and a query that holds the current search string)
    data: {
        results: [],
        query: ''
    },
    // declare methods in this Vue component. here only one method which performs the search is defined
    methods: {
        // make an axios request to the server with the current search query
        search: function() {
            axios.get("http://127.0.0.1:3001/search?q=" + this.query)
                .then(response => {
                    this.results = response.data;

                })
        }
    },
    // declare Vue watchers
    watch: {
        // watch for change in the query string and recall the search method
        query: function() {
            this.search();
        }
    }

})

در این قسمت یک نمونه جدید vue تعریف کردیم و آن را به یک عنصر با شناسه id app متصل کردیم. سپس پروپرتی های زیر را هم تعریف کردیم:

1- query: این پروپرتی را به فیلد جستجو متصل می کنیم.

2- results: یک آرایه شامل تمام نتایج جستجوهای یافت شده است.

سپس از یک پروپرتی تحت عنوان watcher در vue.js استفاده می کنیم. هر زمان که تغییری در کد بوجود بیاید، watcher ها یک عمل خاصی را انجام می دهند

.در اینجا تغییرات پروپرتی query را زیر نظر می گیریم و به محض انجام یک تغییر روی آن، متد search را اجرا می کنیم.

حال اگر دستور node index.js را مجدداً اجرا کرده و به آدرس localhost:3001 مراجعه کنید. باید نتیجه ای مانند زیر را مشاهده کنید.

انجام جستجوی بلادرنگ با ElasticSearch و Vue.js

جستجو از سمت کلاینت

ما می توانیم در سمت کلاینت و بطور مستقیم در ElasticSearch جستجو را انجام دهیم.

برای اینکار ابتدا یک روت جدید به Express ارسال کرده و سرورتان را ریستارت کنید.

//index.js
// decare a new route. This route serves a static HTML template called template2.html
app.get('/v2', function(req, res){
  res.sendFile('template2.html', {
     root: path.join( __dirname, 'views' )
   });
})

در کدهای بالا، یک روت جدید برای آدرس /v2 ایجاد کردیم. این روت فایل template2.html را برگشت می دهد.

سپس باید کتابخانه کلاینت ElasticSearch را از اینجا دانلود کنید. بعد از دانلود، فایل elasticsearch.min.js را به فولدر public پروژه تان کپی کنید.

نکته: در صورت اتصال به ElasticSearch از سمت کلاینت با خطای cors مواجه خواهید شد. برای حل این موضوع، کدهای زیر را در فایل پیکربندی ElasticSearch قرار دهید. برای کسب اطلاع بیشتر به این آدرس مراجعه کنید.

#/etc/elasticsearch/elasticsearch.yml

http.cors.enabled : true
http.cors.allow-origin : "*"

بعد از انجام کارهای فوق، نمونه ElasticSearch تان را ریستارت کنید.

// restart the Elasticsearch service
sudo service elasticsearch restart

سپس یک فایل به نام template2.html در فولدر View ایجاد کنید.

<!-- template2.html -->
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div class="container" id="app">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>Search Cities around the world</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <form action="" class="search-form">
                <div class="form-group has-feedback">
                    <label for="search" class="sr-only">Search</label>
                    <input type="text" class="form-control" name="search" id="search" placeholder="search" v-model="query" >
                    <span class="glyphicon glyphicon-search form-control-feedback"></span>
                </div>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3" v-for="result in results">
            <div class="panel panel-default">
                <div class="panel-heading">
                <!-- display the city name and country  -->
                    {{ result._source.name }}, {{ result._source.country }} 
                </div>
                <div class="panel-body">
                <!-- display the latitude and longitude of the city  -->
                    <p>lat:{{ result._source.lat }}, long: {{ result._source.lng }}.</p>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="/elasticsearch.min.js"></script>
<style>
    .search-form .form-group {
        float: right !important;
        transition: all 0.35s, border-radius 0s;
        width: 32px;
        height: 32px;
        background-color: #fff;
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
        border-radius: 25px;
        border: 1px solid #ccc;
    }

    .search-form .form-group input.form-control {
        padding-right: 20px;
        border: 0 none;
        background: transparent;
        box-shadow: none;
        display: block;
    }

    .search-form .form-group input.form-control::-webkit-input-placeholder {
        display: none;
    }

    .search-form .form-group input.form-control:-moz-placeholder {
        /* Firefox 18- */
        display: none;
    }

    .search-form .form-group input.form-control::-moz-placeholder {
        /* Firefox 19+ */
        display: none;
    }

    .search-form .form-group input.form-control:-ms-input-placeholder {
        display: none;
    }

    .search-form .form-group:hover,
    .search-form .form-group.hover {
        width: 100%;
        border-radius: 4px 25px 25px 4px;
    }

    .search-form .form-group span.form-control-feedback {
        position: absolute;
        top: -1px;
        right: -2px;
        z-index: 2;
        display: block;
        width: 34px;
        height: 34px;
        line-height: 34px;
        text-align: center;
        color: #3596e0;
        left: initial;
        font-size: 14px;
    }
</style>

سپس تگ script را به فایل template2.html اضافه کنید

//template2.html
// instantiate a new Elasticsearch client like you did on the client
var client = new elasticsearch.Client({
    hosts: ['http://127.0.0.1:9200']
});
// create a new Vue instance
var app = new Vue({
    el: '#app',
    // declare the data for the component (An array that houses the results and a query that holds the current search string)
    data: {
        results: [],
        query: ''
    },
    // declare methods in this Vue component. here only one method which performs the search is defined
    methods: {
        // function that calls the elastic search. here the query object is set just as that of the server.
        //Here the query string is passed directly from Vue
        search: function() {
            var body = {
                    size: 200,
                    from: 0,
                    query: {
                        match: {
                            name: this.query
                        }
                    }
                }
                // search the Elasticsearch passing in the index, query object and type
            client.search({ index: 'scotch.io-tutorial', body: body, type: 'cities_list' })
                .then(results => {
                    console.log(`found ${results.hits.total} items in ${results.took}ms`);
                    // set the results to the result array we have 
                    this.results = results.hits.hits;
                })
                .catch(err => {
                    console.log(err)

                });


        }
    },
    // declare Vue watchers
    watch: {
        // watch for change in the query string and recall the search method
        query: function() {
            this.search();
        }
    }

})

کدهای html و جاوا اسکریپت بالا خیلی شبیه به بخش قبلی هستند با این تفاوت که :

1- به جای axios باید از elasticsearch.js استفاده کنید.

2- در بالای تگ Script ، کلاینت ElasticSearch را مقداردهی اولیه میکنیم.

متد search یک درخواست Http  را اجرا نمی کند، بلکه عمل جستجو توسط خود elasticsearch و در سمت سرور انجام می شود.

حال اگر به آدرس localhost:3001/v2  مراجعه کنید، باید تصویر زیر را ببینید.

ساخت یک موتور جستجوی بلادرنگ با Node، Vue و ElasticSearch

نویسنده شوید

دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

پژمان
20 فروردین 1399
سلام.خداقوت مطلبتون خیلی مفید بود.از الستیک سرچ برای سرچ در دیتابیس های دیگه هم میشه استفاده کرد؟(یا که سوالم این معنیو میده:از مونگو دی بی میشه برای سرچ در دیتا بیس های دیگه استفاده کرد؟! :) )

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.