Elasticsearch показывает все результаты, используя прокрутку в узле js

Я в основном пытаюсь показать все записи индексного типа. Теперь, если вы используете match_all() в запросе, elasticsearch по умолчанию показывает 10 результатов. Можно показать все результаты с помощью прокрутки. Я пытаюсь реализовать API прокрутки, но не могу заставить его работать. Он показывает только 10 результатов, мой код:

module.exports.searchAll = function (searchData, callback) {

client.search({
    index: 'test',
    type: 'records',
    scroll: '10s',
    //search_type: 'scan', //if I use search_type then it requires size otherwise it shows 0 result
    body: {
        query: {
            "match_all": {}
        }
    }
}, function (err, resp) {
    client.scroll({
        scrollId: resp._scroll_id,
        scroll: '10s'
    }, callback(resp.hits.hits));
});
}

Кто-нибудь может помочь, пожалуйста?


person Jane    schedule 21.09.2016    source источник


Ответы (6)


Вам нужно повторно вызывать client.scroll до тех пор, пока не будут возвращены записи. Хороший пример в документацию по поиску эластичных материалов. Я воспроизвел их пример кода ниже, немного изменив его, чтобы он соответствовал вашему вопросу.

var allRecords = [];

// first we do a search, and specify a scroll timeout
client.search({
  index: 'test',
  type: 'records',
  scroll: '10s',
  body: {
     query: {
         "match_all": {}
     }
  }
}, function getMoreUntilDone(error, response) {
  // collect all the records
  response.hits.hits.forEach(function (hit) {
    allRecords.push(hit);
  });

  if (response.hits.total !== allRecords.length) {
    // now we can call scroll over and over
    client.scroll({
      scrollId: response._scroll_id,
      scroll: '10s'
    }, getMoreUntilDone);
  } else {
    console.log('all done', allRecords);
  }
});
person Ceilingfish    schedule 21.09.2016
comment
Я пробовал это, прежде чем задать этот вопрос здесь, но это не сработало. Я понял это, хотя. Если я использую search_type: 'scan', то на выходе ничего не появляется, если вы его не укажете, это сработает - person Jane; 23.09.2016
comment
Хорошее расследование @Jane. Я обновил код, чтобы будущие пользователи Google могли с самого начала получить рабочий код. - person Ceilingfish; 10.10.2016
comment
Какой параметр правильный, scrollId или scroll_id в функции прокрутки? - person Mohd Shahid; 25.06.2018
comment
Очень полезно !! Простой и отлично работает. - person DirtyMind; 06.03.2019
comment
Этот запрос может обрабатывать только небольшие наборы данных. Если вы знаете, что запрашиваете большой набор данных, вам следует разделить запрос в соответствии с документацией: elastic.co/guide/en/elasticsearch/reference/6.7/ - person Calle Engene; 07.05.2019
comment
Разделения @CarlEngene позволяют обрабатывать наборы данных параллельно. Нет никаких причин, по которым приведенный выше код не мог бы обработать большое количество записей, просто это заняло бы больше времени. - person Ceilingfish; 30.05.2019

Спасибо @Ceilingfish. Вот модифицированная версия ES6 выше с использованием ожидания

let allRecords = [];

// first we do a search, and specify a scroll timeout
var { _scroll_id, hits } = await esclient.search({
    index: 'test',
    type: 'records',
    scroll: '10s',
    body: {
        query: {
            "match_all": {}
        },
        _source: false
    }
})

while(hits && hits.hits.length) {
    // Append all new hits
    allRecords.push(...hits.hits)

    console.log(`${allRecords.length} of ${hits.total}`)

    var { _scroll_id, hits } = await esclient.scroll({
        scrollId: _scroll_id,
        scroll: '10s'
    })
}

console.log(`Complete: ${allRecords.length} records retrieved`)
person Visualize    schedule 13.09.2017
comment
Какой параметр правильный, scrollId или scroll_id в функции прокрутки? - person Mohd Shahid; 25.06.2018

Запрос для получения всех данных эластичного поиска с помощью клиента Node.js с использованием прокрутки с помощью async/await.

const elasticsearch = require('@elastic/elasticsearch');
async function esconnection(){
  let es =  await new elasticsearch.Client({
    node: "http://192.168.1.1:7200"
  });
  return es;
}
async function getAllUserList(){
    try{
        let userArray = [];
        let query ={
            "query":{
                "match_all": {}
            }
        }   
        let es = await esconnection();
        let {body}=  await es.search({
                    index: 'esIndex',
                    type :"esIndexType",           
                    scroll :'2m', //# Specify how long a consistent view of the index should be maintained for scrolled search
                    size: 100,    //  # Number of hits to return (default: 10)
                    body: query
                    });
        let sid = body['_scroll_id']
        let scroll_size = body['hits']['total']
        let dataLength = body['hits']['hits'].length
        while (scroll_size > 0){
        for(let i=0; i<dataLength;i++){
            if(body['hits']['hits'][i])
            {
            let userData = (body['hits']['hits'][i]['_source'])
            userArray.push(userData)
            }
        }
        sid = body['_scroll_id']
        body = await es.scroll({
            scrollId: sid,
            scroll: '10s'
        })
        body=body.body
        scroll_size = (body['hits']['hits']).length;
        }
        es.close();
        return userArray;
    }  catch(error){
        console.log("Code not working properly: ",`${error}`)
    }
}
person KAPIL PATEL    schedule 03.09.2019

NodeJS потерпел неудачу, когда у эластичного было более 10000 результатов. Вот как я использовал прокрутку.

async function getResultsFromElastic() {
    let responseAll = {};
    responseAll["hits"] = {};
    responseAll.hits.hits = [];
    const responseQueue = [];

    searchQuery = {
                    index: 'test',
                    type: 'records',
                    body: { 
                            query: {
                               "match_all": {}
                            }
                    }
    }
    searchQuery.scroll='10s';
    searchQuery.size=10000;

    responseQueue.push(await esclient.search(searchQuery));

    while (responseQueue.length) {
      const response = responseQueue.shift();

      responseAll.hits.hits = responseAll.hits.hits.concat(response.hits.hits);

      if (response.hits.total == responseAll.hits.hits.length) {
        break;
      }

      // get the next response if there are more to fetch
      responseQueue.push(
        await esclient.scroll({
          scrollId: response._scroll_id,
          scroll: '30s'
        })
      );
    }

    return responseAll;
}
person raka    schedule 13.06.2018

Это то, что я использую с Promises

var EsHelper = function() {
    this.esUrl = esUrl;
    this.indexName = "myIndex";
    this.type = "myIndexType";
    this.elasticClient = new elasticsearch.Client({
        host: esUrl
    });
};

EsHelper.prototype.scrollData = function(response, allHits) {
    return new Promise((resolve, reject) => {
        response.hits.hits.forEach((hit) => allHits.push(hit));
        if (response.hits.total !== allHits.length) {
            this.elasticClient.scroll({
                scroll_id: response._scroll_id,
                scroll: '10s',
            }).then((response) => {
                resolve(this.scrollData(response, allHits));
            }).catch((error) => reject(error));
        } else {
            resolve(allHits);
        }
    });
};

EsHelper.prototype.runSearchWithScroll = function(query) {
    var allHits = [];
    return this.elasticClient.search({
            index: this.indexName,
            type: this.type,
            scroll: '10s',
            body: query
        })
        .then((response) => (this.scrollData(response, allHits)))
        .then((result) => {
            return result;
        });
};

Есть ли лучший способ?

person mahendiran chandrasekar    schedule 17.02.2018

Здесь есть много хорошо написанных ответов, которые решают проблему. Но если кто-то ищет готовое решение, он может перейти сюда и использовать этот пакет — https://github.com/alcacoop/elasticsearch-scroll-stream

Использование довольно простое, и оно просто прекрасно работает. Ниже приведен пример, который я взял из их официальной документации.

const elasticsearch = require('elasticsearch');
const ElasticsearchScrollStream = require('elasticsearch-scroll-stream');

const client = new elasticsearch.Client();

const es_stream = new ElasticsearchScrollStream(client, {
  index: 'your-index',
  type: 'your-type',
  scroll: '10s',
  size: '50',
  _source: ['name'],
  q: 'name:*'
});

es_stream.pipe(process.stdout);

es_stream.on('data', function(data) {
  // Process your results here
});

es_stream.on('end', function() {
  console.log("End");
});
person Sri Harsha Kappala    schedule 23.05.2019
comment
Я пробовал, но в блоке ››es_stream.on('data', function(data) { // Обработайте ваши результаты }); - person Rahul Saini; 30.09.2019
comment
Какую версию elasticsearch вы используете? - person Sri Harsha Kappala; 01.10.2019
comment
версия эластичного поиска = ^ 16.4.0 - person Rahul Saini; 01.10.2019