Reputation: 33
I'm creating an Elasticsearch index using Python API like this:
from elasticsearch import Elasticsearch
es = Elasticsearch()
index_body = {"mappings": {".percolator": {"properties": {"message": {"type": "string", "analyzer": "english"}}}}}
# Creates the index if it doesn't exist
if not es.indices.exists('test'):
es.indices.create(index='test', body=index_body)
print es.exists(index='test', id='1')
The index is created successfully, but when I check for the existence of a document inside the index it fails with this error:
Traceback (most recent call last):
File "main.py", line 12, in <module>
print es.exists(index='test', id='1')
File "/usr/local/lib/python2.7/dist-packages/elasticsearch/client/utils.py", line 68, in _wrapped
return func(*args, params=params, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/elasticsearch/client/__init__.py", line 282, in exists
self.transport.perform_request('HEAD', _make_path(index, doc_type, id), params=params)
File "/usr/local/lib/python2.7/dist-packages/elasticsearch/transport.py", line 307, in perform_request
status, headers, data = connection.perform_request(method, url, params, body, ignore=ignore, timeout=timeout)
File "/usr/local/lib/python2.7/dist-packages/elasticsearch/connection/http_urllib3.py", line 86, in perform_request
self._raise_error(response.status, raw_data)
File "/usr/local/lib/python2.7/dist-packages/elasticsearch/connection/base.py", line 102, in _raise_error
raise HTTP_EXCEPTIONS.get(status_code, TransportError)(status_code, error_message, additional_info)
elasticsearch.exceptions.TransportError: TransportError(503, u'')
If I run this script a second time, with the index already created it works just fine. Does anyone have an idea of what could be going wrong?
Upvotes: 3
Views: 10166
Reputation: 2028
You can add the parameter wait_for_active_shards (defaults to 1) like so:
es.indices.create(index='test', body=index_body, wait_for_active_shards=all)
See also: the elasticsearch-py manual for create(**kwargs)
Upvotes: 0
Reputation: 6559
When creating a new index, you need to wait until all shards are allocated.
The best way I know of how to do is this:
<your_index>/_status
indices.<your_index>.shards
and verify that routing.state = STARTED
everywhereHere's a (PHP) project which did this for unit tests:
protected function _waitForAllocation(Index $index)
{
do {
$settings = $index->getStatus()->get();
$allocated = true;
foreach ($settings['shards'] as $shard) {
if ($shard[0]['routing']['state'] != 'STARTED') {
$allocated = false;
}
}
} while (!$allocated);
}
Wrong answer:
You've to give ES some space before your continue. ES is near realtime, so delays are to be expected. Especially when you're running your code sequentially with next to no delay.
I think you simply need to call the _refresh
endpoint and you're covered.
In practice I've to do the same in my unit tests. They execute very fast and creating/pumping data/destroying indices takes time so in my setUp()
I've a call to _refresh
before handing over to the respective test*()
method. And in some tests, where I index data, I also have to place _refresh
calls.
Usually, during normal operation you don't need to call it shouldn't. Keep in mind that the default refresh_interval
is 1s
. If you're regularly update your index and expect sub-second updates to be reflected (I'm talking about e.g. _search
), that's where you need to start.
Upvotes: 3