web-dev-qa-db-ja.com

Bulk API、スキャン、スクロールによるElasticSearchのインデックスの再作成

私はElastic検索セットアップのインデックスを再作成しようとしています。現在 Elastic検索ドキュメントPython API を使用した例)

しかし、これがどのように機能するかについては少し混乱しています。 Python API:からスクロールIDを取得できました。

es = Elasticsearch("myhost")

index = "myindex"
query = {"query":{"match_all":{}}}
response = es.search(index= index, doc_type= "my-doc-type", body= query, search_type= "scan", scroll= "10m")

scroll_id = response["_scroll_id"]

今私の質問は、これは私にとってどのような用途ですか?スクロールIDを知っていると何が得られますか?ドキュメントには「BulkAPI」を使用するように記載されていますが、scoll_idがこれにどのように影響するのかわかりません。少し混乱しました。

私がscroll_idを正しく持っていることを考慮して、この時点からインデックスを再作成する方法を示す簡単な例を誰かに教えてもらえますか?

12
Zack

以下は、elasticsearch-pyを使用して別のelasticsearchノードにインデックスを再作成する例です。

from elasticsearch import helpers
es_src = Elasticsearch(["Host"])
es_des = Elasticsearch(["Host"])

helpers.reindex(es_src, 'src_index_name', 'des_index_name', target_client=es_des)

クエリの結果を別のインデックスに再インデックスすることもできます。その方法は次のとおりです。

from elasticsearch import helpers
es_src = Elasticsearch(["Host"])
es_des = Elasticsearch(["Host"])

body = {"query": {"term": {"year": "2004"}}}
helpers.reindex(es_src, 'src_index_name', 'des_index_name', target_client=es_des, query=body)
9
hamed

こんにちは、スクロールAPIを使用して、最も効率的な方法ですべてのドキュメントを調べることができます。 scroll_idを使用すると、特定のスクロール要求のためにサーバーに保存されているセッションを見つけることができます。したがって、より多くのアイテムを取得するには、リクエストごとにscroll_idを指定する必要があります。

バルクAPIは、ドキュメントのインデックス作成をより効率的にするためのものです。コピーとインデックス作成の場合は両方が必要ですが、実際には関連していません。

私はそれがどのように機能するかについてより良い考えを得るのを助けるかもしれないいくつかのJavaコードを持っています。

    public void reIndex() {
    logger.info("Start creating a new index based on the old index.");

    SearchResponse searchResponse = client.prepareSearch(MUSIC_INDEX)
            .setQuery(matchAllQuery())
            .setSearchType(SearchType.SCAN)
            .setScroll(createScrollTimeoutValue())
            .setSize(SCROLL_SIZE).execute().actionGet();

    BulkProcessor bulkProcessor = BulkProcessor.builder(client,
            createLoggingBulkProcessorListener()).setBulkActions(BULK_ACTIONS_THRESHOLD)
            .setConcurrentRequests(BULK_CONCURRENT_REQUESTS)
            .setFlushInterval(createFlushIntervalTime())
            .build();

    while (true) {
        searchResponse = client.prepareSearchScroll(searchResponse.getScrollId())
                .setScroll(createScrollTimeoutValue()).execute().actionGet();

        if (searchResponse.getHits().getHits().length == 0) {
            logger.info("Closing the bulk processor");
            bulkProcessor.close();
            break; //Break condition: No hits are returned
        }

        for (SearchHit hit : searchResponse.getHits()) {
            IndexRequest request = new IndexRequest(MUSIC_INDEX_NEW, hit.type(), hit.id());
            request.source(hit.sourceRef());
            bulkProcessor.add(request);
        }
    }
}
7

この問題が発生した場合は、Pythonクライアントから次のAPIを使用して、インデックスを再作成できます。

https://elasticsearch-py.readthedocs.org/en/master/helpers.html#elasticsearch.helpers.reindex

これにより、スクロールして検索してすべてのデータを取得し、バルクAPIを使用してデータを新しいインデックスに配置する必要がなくなります。

5
syd_barrett

インデックスを再作成する最良の方法は、Elasticsearchの組み込み Reindex API を使用することです。これは、十分にサポートされており、既知の問題に対して回復力があるためです。

Elasticsaerch Reindex APIは、スクロールとバルクインデックスをバッチで使用し、データのスクリプト変換を可能にします。 Pythonでは、同様のルーチンを開発できます。

#!/usr/local/bin/python
from elasticsearch import Elasticsearch
from elasticsearch import helpers

src = Elasticsearch(['localhost:9202'])
dst = Elasticsearch(['localhost:9200'])

body = {"query": { "match_all" : {}}}

source_index='src-index'
target_index='dst-index'
scroll_time='60s'
batch_size='500'

def transform(hits):
    for h in hits:
        h['_index'] = target_index
        yield h

rs = src.search(index=[source_index],
        scroll=scroll_time,
        size=batch_size,
        body=body
   )

helpers.bulk(dst, transform(rs['hits']['hits']), chunk_size=batch_size)

while True:
    scroll_id = rs['_scroll_id']
    rs = src.scroll(scroll_id=scroll_id, scroll=scroll_time)
    if len(rs['hits']['hits']) > 0:
        helpers.bulk(dst, transform(rs['hits']['hits']), chunk_size=batch_size)
    else:
        break;
0