Support of Elasticsearch for Node.js

CAST supports Elasticsearch via its com.castsoftware.nodejs extension. Details about how this support is provided for Node.js source code is discussed below.

Supported Client Libraries

Library

Supported

Elasticsearch

Supported Operations

Operation Methods Supported
Insert

index

Update

update

updateByQuery

Select

search

msearch

explain

get

mget

Delete 

delete

deleteByQuery

Objects

Icon  Description

Node.js Elasticsearch Cluster

Node.js Elasticsearch Unknown Cluster

Node.js Elasticsearch Index

Node.js Elasticsearch Unknown Index 

Links are created for transaction and function point needs:

Link type Source and destination of link  Methods supported
parentLink

Between Elasticsearch Cluster object and Elasticsearch Index object

-
useXLink Between the caller Node.js Initialization / Function objects and Elasticsearch Index objects

bulk

useInsertLink Between the caller Node.js Initialization / Function objects and Elasticsearch Index objects

index

useDeleteLink Between the caller Node.js Initialization / Function objects and Elasticsearch Index objects

delete

deleteByQuery

useSelectLink

Between the caller Node.js Initialization / Function objects and Elasticsearch Index objects

search

msearch

explain

get

mget

useUpdateLink Between the caller Node.js Initialization / Function objects and Elasticsearch Index objects

update

updateByQuery

What results can you expect?

Some example scenarios are shown below:

Cluster creation

Older version: 16.x

const elasticsearch = require('elasticsearch');

// list of string
let client = new elasticsearch.Client({
    hosts: [
        'https://[username]:[password]@[server]:[port]/',
        'https://[username]:[password]@[server]:[port]/'
    ]
});

// object
let client1 = new elasticsearch.Client({
    host: {
        protocol: 'https',
        host: 'my-site.com',
        port: 80,
        path: '/elasticsearch/'
    }
});

// list of object
let client2 = new elasticsearch.Client({
    hosts: [
        {
            protocol: 'https',
            host: 'box1.server.org',
            port: 56394,
            // these custom values are used below by the selector
            country: 'EU',
            weight: 10
        },
        {
            protocol: 'https',
            host: 'box2.server.org',
            port: 56394,
            // these custom values are used below by the selector
            country: 'US',
            weight: 50
        }
    ]
});

// list of string and object
let client3 = new elasticsearch.Client({
    hosts: [
        'https://[username]:[password]@[server]:[port]/',
        {
            protocol: 'https',
            host: 'my-site.com',
            port: 80,
            path: '/elasticsearch/'
        }
    ]
});

Newer version: >= 5.x

const {Client, errors} = require('@elastic/elasticsearch');

// string
const client = new Client({node: 'http://localhost:9200'});

// URL object
const client2 = new Client({node: new URL('http://127.0.0.1')});

// list of string and URL object
const client3 = new Client({
    nodes: [
        'http://192.168.167.1',
        new URL('google.com')
    ]
});

Insert operation

const response = client.index({
  index: 'myindex',
  type: 'mytype',
  id: '1',
  body: {
    title: 'Test 1',
    tags: ['y', 'z'],
    published: true,
  }
});

Update operation

// string
let response = client.update({
    index: 'indexA',
    type: 'mytype',
    id: '1',
    body: {
        // put the partial document under the `doc` key
        doc: {
            title: 'Updated'
        }
    }
});

// string
response = client.updateByQuery({
        index: 'indexB',
        type: type,
        body: {
            "query": {"match": {"animal": "bear"}},
            "script": {"inline": "ctx._source.color = 'pink'"}
        }
    }, function (err, res) {
        if (err) {
            reportError(err)
        }
        cb(err, res)
    }
);

// list of string
response = client.updateByQuery({
        index: ['indexC', 'indexD'],
        type: type,
        body: {
            "query": {"match": {"animal": "bear"}},
            "script": {"inline": "ctx._source.color = 'pink'"}
        }
    }, function (err, res) {
        if (err) {
            reportError(err)
        }
        cb(err, res)
    }
);

Select operation 

let response = client.get({
  index: 'indexA',
  type: 'mytype',
  id: 1
});

Delete operation

client.delete({
    index: 'indexA',
    type: 'mytype',
    id: '1'
});

Bulk

client.bulk({
  body: [
    // action description
    { index:  { _index: 'indexA', _type: 'mytype', _id: 1 } },
     // the document to index
    { title: 'foo' },
    // action description
    { update: { _index: 'indexB', _type: 'mytype', _id: 2 } },
    // the document to update
    { doc: { title: 'foo' } },
    // action description
    { delete: { _index: 'indexC', _type: 'mytype', _id: 3 } },
    // no document needed for this delete
  ]
}, function (err, resp) {
  // ...
});

Known Limitations

  • For HTML5 Extension version < …
    • Identifiers inside a hardcoded list into a dictionary are not resolved, see:
// LIMITATION
a = 'foo'
client.updateByQuery({
    index: ['bar', a] // In this case « a » won't be resolved 
});

// NO LIMITATION
b = ['bar', a];
client.updateByQuery({
    index: b // In this case « a » will be resolved 
});
  • Operation operating on all indexes (no index argument or index = _all) do not create links

  • Using client inside object is not supported, see:

// In wrapper.js
const elasticsearch = require('elasticsearch');

var self = {};

self.client = new elasticsearch.Client({
  host: 'client.org'
});


module.exports = self;

//----------------------------------------------------------

// In app.js
const ElasticsearchWrapper = require('./wrapper.js');

ElasticsearchWrapper.client.deleteByQuery({  // -> this call won't be detected as the client is wrapped inside an object
        index: 'some_index',
    },
    function (error, response) {
      if (error)
        sails.log.info("error ", error);
    }
);