class Index(object): def __init__(self, db, config): self.db = db self.config = config self.es = Elasticsearch( hosts=self.config.hosts, **self.config.get("client_options", {}) ) self.types = AttributeDict() self._index = config.index def register(self, type_): obj = type_(self) self.types[obj._type] = obj def reindex(self, alias=True, keep_old=False): # Generate an Index Name for Warehouse index = "".join([ self._index, binascii.hexlify(os.urandom(4)).decode("ascii"), ]) # Create this index self.es.indices.create(index, { "mappings": { doc_type._type: doc_type.get_mapping() for doc_type in self.types.values() }, }) # Index everything into the new index for doc_type in self.types.values(): doc_type.index_all(index=index) # Update the alias unless we've been told not to if alias: self.update_alias(self._index, index, keep_old=keep_old) def update_alias(self, alias, index, keep_old=False): # Get the old index from ElasticSearch try: old_index = list(self.es.indices.get_alias(self._index))[0] except TransportError as exc: if not exc.status_code == 404: raise old_index = None # Remove the alias to the old index if it exists if old_index is not None: actions = [{"remove": {"index": old_index, "alias": alias}}] else: actions = [] # Add the alias to the new index actions += [{"add": {"index": index, "alias": alias}}] # Update To the New Index self.es.indices.update_aliases({"actions": actions}) # Delete the old index if it exists and unless we're keeping it if not keep_old and old_index is not None: self.es.indices.delete(old_index)