/**
  * @param \Elastica\Document[] $documents
  * @param string|null $shardTimeout Timeout in Elasticsearch time format (1m, 15s, ...)
  */
 protected function sendDocuments(array $documents, $shardTimeout = null)
 {
     if (count($documents) === 0) {
         return;
     }
     try {
         // addDocuments (notice plural) is the bulk api
         $bulk = new \Elastica\Bulk(Connection::getSingleton()->getClient2());
         if ($shardTimeout !== null) {
             $bulk->setShardTimeout($shardTimeout);
         }
         $index = Connection::getFlowIndex(wfWikiId());
         $type = $index->getType($this->getTypeName());
         $bulk->setType($type);
         $bulk->addDocuments($documents);
         $bulk->send();
     } catch (\Exception $e) {
         $documentIds = array_map(function ($doc) {
             return $doc->getId();
         }, $documents);
         wfWarn(__METHOD__ . ': Failed updating documents (' . implode(',', $documentIds) . '): ' . $e->getMessage());
     }
 }
 /**
  * We want to retrieve the total amount of search word hits
  * (static::termsAggregation) but our search terms may not be how
  * ElasticSearch stores the words in its index.
  * Elastic will "analyze" text (perform stemming, etc) and store
  * the terms in a normalized way.
  * AFAICT, there is not really a way to get to that information
  * from within a search query.
  *
  * Luckily, since 1.0, Elastic supports _termvector, which gives
  * you statistics about the terms in your document.
  * Since 1.4, Elastic supports feeding _termvector documents to
  * analyze.
  * We're going to (ab)use this by letting it respond with term
  * information on a bogus document that contains only our current
  * search terms.
  * So we'll give it a document with just our keywords for the
  * column that we're searching in (revisions.text) and Elastic will
  * use that column's configuration to analyze the text we feed it.
  * It will then respond with the normalized terms & their stats.
  *
  * @param string $terms
  * @return array
  */
 protected function getTerms($terms)
 {
     $terms = preg_split('/\\s+/', $terms);
     // _termvectors only works on a type, but our types are
     // configured exactly the same so it doesn't matter which
     $types = Connection::getAllTypes();
     $searchable = Connection::getFlowIndex($this->indexBaseName);
     $searchable = $searchable->getType(array_pop($types));
     $query = array('doc' => array('revisions' => array('text' => $terms)), "fields" => array("revisions.text"));
     // Elastica has no abstraction over _termvector like it has
     // for _query, so just do the request ourselves
     $response = $searchable->request('_termvector', Request::POST, $query, array());
     $data = $response->getData();
     return array_keys($data['term_vectors']['revisions.text']['terms']);
 }
 protected function getOldHeaderType()
 {
     $index = Connection::getFlowIndex($this->indexBaseName);
     return $index->getType(Connection::HEADER_TYPE_NAME);
 }