Blog

How to Integrate Amazon Elasticsearch Service with Backendless

by on February 28, 2019

Amazon Elasticsearch Service (Amazon ES) is a service that can store a lot of data and provide a full text-based search, along with other cool features. In this article, we’ll show you how to integrate Amazon ES into your Backendless project. Of course, you may be able to accomplish what you’re looking for by using the new Backendless Navigator.

Save objects to Amazon ES

To save objects to the Amazon ES with Backendless, you need to:

  1. Create an Amazon ES domain
  2. Create after event handlers in Backendless Console
  3. Download generated code
  4. Write JavaScript code to save objects

Once you have an Amazon ES domain, create the afterCreate event handler:
Create Event Handler for Amazon ES

Download JavaScript code and open it the IDE of your choice.

Open package.json and add http-aws-es, elasticsearch, and aws-sdk dependencies. Your file should then look like the following:

{
  "name": "AmzonESArt-servercode",
  "version": "1.0.0",
  "scripts": {
    "debug": "coderunner debug",
    "deploy": "coderunner deploy"
  },
  "devDependencies": {
    "backendless-coderunner": "^4.6.4"
  },
  "license": "MIT",
  "dependencies": {
    "aws-sdk": "^2.268.1",
    "elasticsearch": "^15.1.1",
    "http-aws-es": "^6.0.0"
  }
}

Open coderunner.json and exclude aws-sdk as it is already added to the Backendless cloud:

{
  "backendless": {
    "apiServer": "https://api.backendless.com",
    "msgBroker": {
      "host": "cl.backendless.com",
      "port": 6379
    }
  },
  "app": {
   "id": "your-application-id",
   "apiKey": "your-api-key",
   "model": "default",
   "exclude": [
       "node_modules/aws-sdk/**",
       "package.json",
       "coderunner.json",
       "README.md",
       "servercode.iml",
       "servercode.ipr",
       "servercode.iws"
    ]
  }
}

Open the afterCreate.js file and paste the following code:

Backendless.ServerCode.Persistence.afterCreate( '*', function ( req ) {
let options = {
   hosts: ['https://your-aws-domain.es.amazonaws.com'], // array of amazon es hosts (required)
   connectionClass: require( 'http-aws-es' ), // use this connector (required)
   awsConfig: new AWS.Config( {
                                region: 'eu-central-1', credentials: new AWS.Credentials( {
                                                                       accessKeyId: 'your-access-key-id',
                                                                       secretAccessKey: 'your-secret-key'
                                                                      } )
                              } ),
   httpOptions: {} // set httpOptions on aws-sdk's request. default to aws-sdk's config.httpOptions
};
let es = require( 'elasticsearch' ).Client( options );
return new Promise( ( resolve, reject ) => {
   es.create( {
              index: req.context.eventContext.toLowerCase(),
              type: 'json',
              id: req.item.objectId,
              body: req.item
            }, ( err, resp ) => {
   console.log( resp );
   if( err ) {
     console.error( err );
     reject( err );
   }
   else {
     resolve( )
   }
 } );
} )

Now, each time you create an object in a Backendless data table, it will be saved to the Amazon ES as well.

Search in Amazon ES

Let’s create a Backendless service to search in the Amazon ES cloud. To do this, add the esSearchService.js file to the project that was created in the previous step.

'use strict';
let AWS = require( 'aws-sdk' )
class AmazonESSearchService {
 /**
  * @param {String} tableName
  * @param {String} query
  * @returns {Promise<Array>}
  */
 getFind( tableName, query ) {
   let options = {
     hosts: ['https://amzon es domain'], // array of amazon es hosts (required)
     connectionClass: require( 'http-aws-es' ), // use this connector (required)
     awsConfig: new AWS.Config( {
                                  region: 'eu-central-1', credentials: new AWS.Credentials( {
                                                                                    accessKeyId: 'access key id',
                                                                                    secretAccessKey: 'vaccess key id'
                                                                                  } )
                                } ), // set an aws config e.g. for multiple clients to different regions
     httpOptions: {} // set httpOptions on aws-sdk's request. default to aws-sdk's config.httpOptions
   };
   let es = require( 'elasticsearch' ).Client( options );
   return new Promise( ( resolve, reject ) => {
     es.search( {
                  index: tableName,
                  q: query
                }, ( err, resp ) => {
       console.log( resp );
       if( err ) {
         console.error( err );
         reject( err );
       }
       else {
         resolve( resp )
       }
     } );
   } )
 }
}
Backendless.ServerCode.addService(AmazonESSearchService);

Then run CodeRunner in the debug mode, or deploy the code.

Go to Backendless Console and try to search:
Invoke Amazon Elasticsearch Service in Backendless

Closing

In this article, we used https://www.npmjs.com/package/http-aws-es which makes elasticsearch-js compatible with Amazon ES. To see more options for using ES API, check out the ES documentation.

Leave a Reply