Node.js で Elasticsearch にクエリ
Elasticsearch の公式クライアントで叩く。
const elasticsearch = require('elasticsearch'); const client = new elasticsearch.Client({ host: 'http://localhost:9200' httpAuth: 'user:password' log: 'trace' }); client.search({ index: index, type: type, size: size, body: { _source: [ // to be included fields ], aggs: { // aggregation contents }, query:{ // query contents } } });
直で REST API 叩く時とちょっとだけ違っていて、 query や aggs の前に body
を挟む必要があったりするので注意。
.search
の戻り値は Promise になっていて、中身はこんな以下のように取得する。これは REST API の戻り値と (たぶん) おなじ。
client.search().then(response => { const documents = response.hits.hits.(x=>x._source); const aggregated = response.aggregations; // ... });
当然、
function get() { return client.search().then(response => return response;) } get().then(result => { // ... });
とか、
const result = await client.search();
とか書ける。
Scroll API で取得したい場合はちょっと違って
let documents = []; client.search({ index: index, type: type, size: size, scroll: chacheTime body: { query:{ // query contents } } }, function scroll(error, response) { documents = documents.concat(response.hits.hits); if(response.hits.total !== documents.length) { client.scroll({ scrollId: response._scroll_id, scroll: cacheTime }, scroll) } else { return documents; } });
のようになる。この戻り値が Promise とならず、 client.search({...}, function(){...}).then()
のように書けない。なので 上述の例と同じように扱いたければ
const promise = new Promise((resolve, reject) => { let documents = []; client.search({ // ... }, function scroll(error, response) { documents = documents.concat(response.hits.hits); if(response.hits.total !== documents.length) { client.scroll({ scrollId: response._scroll_id, scroll: cacheTime }, scroll) } else { resolve(documents); } }) })
と Promise オブジェクトを new してやる必要がある。
これはもっとスマートに解決できる方法があるかも?