Пример #1
0
 /**
  * Filter search results so only documents that are viewable by the current
  * user will be returned...
  *
  * @param \Elastica\Query\BoolQuery $elasticaQueryBool
  */
 protected function applySecurityContext($elasticaQueryBool)
 {
     $roles = $this->getCurrentUserRoles();
     $elasticaQueryRoles = new \Elastica\Query\Terms();
     $elasticaQueryRoles->setTerms('view_roles', $roles)->setMinimumMatch(1);
     $elasticaQueryBool->addMust($elasticaQueryRoles);
 }
Пример #2
0
 /**
  * @Route("/search", name="search")
  * @Method("GET")
  * @Template("AppBundle:Search:index.html.twig")
  */
 public function searchAction(Request $request)
 {
     $user = $this->get('security.context')->getToken()->getUser();
     $searchKey = strtolower($request->query->get('searchKey'));
     // $user = $this->get('security.context')->getToken()->getUser();
     $finderBucket = $this->container->get('fos_elastica.index.search.bucket');
     $finderItem = $this->container->get('fos_elastica.index.search.item');
     $boolQuery1 = new \Elastica\Query\BoolQuery();
     $terms1 = new \Elastica\Query\Terms();
     $terms1->setTerms('name', array($searchKey));
     $boolQuery1->addMust($terms1);
     $queryId1 = new \Elastica\Query\Terms();
     $queryId1->setTerms('id', [$user->getId()]);
     $nestedQuery1 = new \Elastica\Query\Nested();
     $nestedQuery1->setPath('user');
     $nestedQuery1->setQuery($queryId1);
     $boolQuery1->addMust($nestedQuery1);
     $buckets = $finderBucket->search($boolQuery1);
     $boolQuery2 = new \Elastica\Query\BoolQuery();
     $termsTitle = new \Elastica\Query\Terms();
     $termsContent = new \Elastica\Query\Terms();
     $termsTitle->setTerms('title', array($searchKey));
     $boolQuery2->addMust($termsTitle);
     $termsContent->setTerms('content', array($searchKey));
     $boolQuery2->addShould($termsContent);
     $queryId2 = new \Elastica\Query\Terms();
     $queryId2->setTerms('id', [$user->getId()]);
     $nestedQuery2 = new \Elastica\Query\Nested();
     $nestedQuery2->setPath('user');
     $nestedQuery2->setQuery($queryId2);
     $boolQuery2->addMust($nestedQuery2);
     $items = $finderItem->search($boolQuery2);
     return ['searchKey' => $searchKey, 'buckets' => $buckets, 'items' => $items, 'allBuckets' => $this->getAllBuckets($user)];
 }
Пример #3
0
 public function getArticles($user, $searchTerm, $page, $pageOffset, $category, $colors, $finder)
 {
     $boolQuery = new \Elastica\Query\BoolQuery();
     if ($category != NULL) {
         $categoryQuery = new \Elastica\Query\Terms();
         $categoryQuery->setTerms('custdata.customCatRef', array($category));
         $boolQuery->addMust($categoryQuery);
     }
     if ($searchTerm) {
         $fieldQuery = new \Elastica\Query\Match();
         $fieldQuery->setFieldQuery('customerRef', $user->getCustomerRef());
         $boolQuery->addMust($fieldQuery);
         $fieldQuery = new \Elastica\Query\Match();
         $fieldQuery->setFieldQuery('allField', $searchTerm);
         $fieldQuery->setFieldOperator('allField', 'AND');
         $fieldQuery->setFieldMinimumShouldMatch('allField', '70%');
         $fieldQuery->setFieldFuzziness('allField', '0.8');
         $fieldQuery->setFieldAnalyzer('allField', 'custom_search_analyzer');
         $boolQuery->addMust($fieldQuery);
     } else {
         $fieldQuery = new \Elastica\Query\MatchAll();
         $boolQuery->addMust($fieldQuery);
     }
     $fieldQuery = new \Elastica\Query\Nested();
     $fieldQuery->setPath('custdata.custcat.perm');
     $boolNested = new \Elastica\Query\BoolQuery();
     $fieldNested = new \Elastica\Query\Match();
     $fieldNested->setField('custdata.custcat.perm.permStatus', 1);
     $boolNested->addMust($fieldNested);
     $fieldNested = new \Elastica\Query\Match();
     $fieldNested->setField('custdata.custcat.perm.userRef', $user->getId());
     $boolNested->addMust($fieldNested);
     $fieldQuery->setQuery($boolNested);
     $boolQuery->addMust($fieldQuery);
     if ($colors != NULL) {
         $colorQuery = new \Elastica\Query\Terms();
         $colorQuery->setTerms('variants.variantvalues.otherTerms', $colors);
         $colorNested = new \Elastica\Query\Nested('variants');
         $colorNested->setPath('variants.variantvalues');
         $colorNested->setQuery($colorQuery);
         $boolQuery->addMust($colorNested);
     }
     $query = new \Elastica\Query();
     $query->setQuery($boolQuery);
     $query->setSize(12);
     $query->setFrom($pageOffset);
     $articles = $finder->find($query);
     $result = array("articles" => $articles, "rQuery" => $query);
     return $result;
 }
Пример #4
0
 /**
  * Filter search results so only documents that are viewable by the current user will be returned...
  *
  * @param \Elastica\Query\Bool $elasticaQueryBool
  */
 protected function applySecurityContext($elasticaQueryBool)
 {
     $roles = array();
     if (!is_null($this->securityContext)) {
         $user = $this->securityContext->getToken()->getUser();
         if ($user instanceof BaseUser) {
             $roles = $user->getRoles();
         }
     }
     // Anonymous access should always be available for both anonymous & logged in users
     if (!in_array('IS_AUTHENTICATED_ANONYMOUSLY', $roles)) {
         $roles[] = 'IS_AUTHENTICATED_ANONYMOUSLY';
     }
     $elasticaQueryRoles = new \Elastica\Query\Terms();
     $elasticaQueryRoles->setTerms('view_roles', $roles)->setMinimumMatch(1);
     $elasticaQueryBool->addMust($elasticaQueryRoles);
 }
Пример #5
0
 /**
  * @group unit
  */
 public function testSetPostFilterToArrayCast()
 {
     $query = new Query();
     $postFilter = new \Elastica\Query\Terms();
     $postFilter->setTerms('key', array('term'));
     $query->setPostFilter($postFilter);
     $postFilter->setTerms('another key', array('another term'));
     $anotherQuery = new Query();
     $anotherQuery->setPostFilter($postFilter);
     $this->assertEquals($query->toArray(), $anotherQuery->toArray());
 }
Пример #6
0
 public function getBestImg($searchTerm, $articleRef, $colors, $finder)
 {
     $boolQuery = new \Elastica\Query\BoolQuery();
     if ($searchTerm) {
         $fieldQuery = new \Elastica\Query\Match();
         $fieldQuery->setFieldQuery('desc1', $searchTerm);
         $fieldQuery->setFieldOperator('desc1', 'OR');
         $fieldQuery->setFieldMinimumShouldMatch('desc1', '80%');
         $fieldQuery->setFieldAnalyzer('desc1', 'custom_search_analyzer');
         $boolQuery->addShould($fieldQuery);
         $fieldQuery = new \Elastica\Query\Match();
         $fieldQuery->setFieldQuery('desc2', $searchTerm);
         $fieldQuery->setFieldOperator('desc2', 'OR');
         $fieldQuery->setFieldMinimumShouldMatch('desc2', '80%');
         $fieldQuery->setFieldAnalyzer('desc2', 'custom_search_analyzer');
         $varTerms = explode(" ", $searchTerm);
         $boolQuery->addShould($fieldQuery);
         $colorQuery = new \Elastica\Query\Terms();
         $colorQuery->setTerms('variantvalues.otherTerms', $varTerms);
         $colorNested = new \Elastica\Query\Nested('variantvalues');
         $colorNested->setPath('variantvalues');
         $colorNested->setQuery($colorQuery);
         $boolQuery->addShould($colorNested);
         if ($colors != NULL) {
             $fieldQuery = new \Elastica\Query\Terms();
             $fieldQuery->setTerms('otherTerms', $colors);
             $boolQuery->addShould($fieldQuery);
         }
     }
     $articleRefQuery = new \Elastica\Query\Terms();
     $articleRefQuery->setTerms('articleRef', array($articleRef));
     $boolQuery->addMust($articleRefQuery);
     if ($colors != NULL) {
         $colorQuery = new \Elastica\Query\Terms();
         $colorQuery->setTerms('variantvalues.otherTerms', $colors);
         $colorNested = new \Elastica\Query\Nested('variantvalues');
         $colorNested->setPath('variantvalues');
         $colorNested->setQuery($colorQuery);
         $boolQuery->addMust($colorNested);
     }
     $query = new \Elastica\Query();
     $query->setQuery($boolQuery);
     $query->setSize(12);
     $articleVar = $finder->find($query);
     return $articleVar;
 }
Пример #7
0
 public function searchAction(Request $request)
 {
     $em = $this->getDoctrine()->getManager();
     $username = $request->query->get('oci_username');
     $password = $request->query->get('oci_password');
     $hookurl = $request->query->get('hookurl');
     $response = new Response();
     $response->headers->clearCookie('OCIHOOK');
     $response->headers->clearCookie('OrthCookie');
     $response->sendHeaders();
     $response->send();
     $response->headers->setCookie(new Cookie('OCIHOOK', $hookurl));
     $cookieValue = uniqid();
     $response->headers->setCookie(new Cookie('OrthCookie', uniqid()));
     $response->sendHeaders();
     $response->send();
     $query = $em->createQuery("SELECT u FROM Orth\\IndexBundle\\Entity\\Users u WHERE u.email = :username");
     $query->setParameter('username', $username);
     $user = $query->getOneOrNullResult();
     if ($user) {
         // Get the encoder for the users password
         $encoder_service = $this->get('security.encoder_factory');
         $encoder = $encoder_service->getEncoder($user);
         // Note the difference
         if ($encoder->isPasswordValid($user->getPassword(), $password, '$2a$12$uWepESKverBsrLAuOPY')) {
             // Get profile list
         } else {
             dump('fail1');
             exit;
         }
     } else {
         dump('fail');
         exit;
     }
     $token = new UsernamePasswordToken($user, null, "default", $user->getRoles());
     $this->get("security.context")->setToken($token);
     //now the user is logged in
     //now dispatch the login event
     $request = $this->get("request");
     $event = new InteractiveLoginEvent($request, $token);
     $this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
     if ($request->query->get('FUNCTION') == NULL) {
         return $this->redirectToRoute('orth_index_homepage', array(), 301);
     }
     $searchTerm = $request->query->get('SEARCHSTRING');
     $page = 0;
     $pageOffset = 0;
     $catId = $request->query->get('cid');
     $finder = $this->container->get('fos_elastica.finder.search.article');
     $boolQuery = new \Elastica\Query\BoolQuery();
     if ($request->query->get('c') != NULL and $request->query->get('SEARCHSTRING') == NULL) {
         $catid = $request->query->get('c');
         $categoryArray = [$request->query->get('c')];
         $rootCategories = $em->getRepository('OrthIndexBundle:Categories')->findBy(array('parentId' => $catid));
         foreach ($rootCategories as $childCategory) {
             $childCategories = $em->getRepository('OrthIndexBundle:Categories')->findBy(array('parentId' => $childCategory->getId()));
             $categoryArray[] = $childCategory->getId();
             foreach ($childCategories as $grandchildCategory) {
                 $categoryArray[] = $grandchildCategory->getId();
             }
         }
         $categoryQuery = new \Elastica\Query\Terms();
         $categoryQuery->setTerms('catRef', $categoryArray);
         $boolQuery->addMust($categoryQuery);
     } elseif ($request->query->get('c') != NULL) {
         $catid = $request->query->get('c');
         $categoryQuery = new \Elastica\Query\Terms();
         $categoryQuery->setTerms('catRef', array($catid));
         $boolQuery->addMust($categoryQuery);
     }
     if ($request->query->get('SEARCHSTRING')) {
         $fieldQuery = new \Elastica\Query\Match();
         $fieldQuery->setFieldQuery('allField', $searchTerm);
         $fieldQuery->setFieldOperator('allField', 'AND');
         $fieldQuery->setFieldMinimumShouldMatch('allField', '80%');
         $fieldQuery->setFieldAnalyzer('allField', 'custom_search_analyzer');
         $boolQuery->addMust($fieldQuery);
     }
     $query = new \Elastica\Query();
     $query->setQuery($boolQuery);
     $totalpages = ceil(count($finder->find($query)) / 12);
     $query->setSize(100);
     $query->setFrom($pageOffset);
     $articles = $finder->find($query);
     foreach ($articles as $article) {
         $variants = $article->getVariants();
         foreach ($variants as $variant) {
             $price = $em->getRepository('OrthIndexBundle:ArticleSuppliers')->getCustomPrice(array('id' => $variant), $user);
             $category = $em->getRepository('OrthIndexBundle:Categories')->getRootCategory($article->getCategory()->getId());
             $attribute = "";
             foreach ($variant->getVariantvalues() as $values) {
                 $attribute .= " " . $values->getAttrname()->getAttributeName() . " " . $values->getAttributeValue() . "" . $values->getAttributeUnit();
             }
             if ($variant->getVariantvalues()) {
                 if ($article->getImages()[0]) {
                     $image = $article->getImages()[0]->getPicName();
                 } else {
                     $image = 'nopicture_all.jpg';
                 }
                 $result[] = array('shortName' => $article->getShortName() . "" . $attribute, 'articleNumber' => $variant->getSupplierArticleNumber(), 'price' => $price, 'category' => $category, 'image' => $image);
             }
         }
     }
     return $this->render('OrthIndexBundle:Oci:ocioutput.html.twig', array('results' => $result, 'page' => $page, 'totalpages' => $totalpages, 'hookurl' => $hookurl));
 }
Пример #8
0
 public function search($category, PlaceSearch $placeSearch)
 {
     // we create a query to return all the articles
     // but if the criteria title is specified, we use it
     $boolQuery = new \Elastica\Query\Bool();
     /*Fetch only VALIDATED place*/
     $queryStatus = new \Elastica\Query\Match();
     $queryStatus->setFieldQuery('place.status', StatusType::VALIDATED);
     $boolQuery->addMust($queryStatus);
     if ($category !== null) {
         $queryCategory = new \Elastica\Query\Match();
         $queryCategory->setFieldQuery('place.categories.slug', $category);
         $boolQuery->addMust($queryCategory);
     }
     if ($placeSearch->getBirthdayDiscount() != null && $placeSearch->getBirthdayDiscount() > 0) {
         $queryRange = new \Elastica\Query\Range();
         $queryRange->setParam('place.birthdayDiscount', ['gte' => 1]);
         $boolQuery->addMust($queryRange);
     }
     if (($placeSearch->getName() != null || $placeSearch->getCategories() != null) && $placeSearch != null) {
         if ($placeSearch->getName() != null) {
             $query = new \Elastica\Query\Match();
             $query->setFieldQuery('place.name', $placeSearch->getName());
             $query->setFieldFuzziness('place.name', 1);
             $query->setFieldMinimumShouldMatch('place.name', '10%');
             $boolQuery->addMust($query);
         }
         if ($placeSearch->getCategories() != null) {
             foreach ($placeSearch->getCategories() as $cat) {
                 $categories[] = $cat->getName();
             }
             $queryCategories = new \Elastica\Query\Terms();
             $queryCategories->setTerms('place.categories', $categories);
             $boolQuery->addShould($queryCategories);
         }
     } else {
         $query = new \Elastica\Query\MatchAll();
     }
     $baseQuery = $boolQuery;
     // then we create filters depending on the chosen criterias
     $boolFilter = new \Elastica\Filter\Bool();
     $active = new \Elastica\Filter\Term(['membershipSubscriptions.statusSubscription' => MembershipStatusType::ACTIVE]);
     $boolFilter->addMust($active);
     /*
         Dates filter
         We add this filter only the getIspublished filter is not at "false"
     */
     //        if("false" != $articleSearch->getIsPublished()
     //           && null !== $articleSearch->getDateFrom()
     //           && null !== $articleSearch->getDateTo())
     //        {
     //            $boolFilter->addMust(new \Elastica\Filter\Range('publishedAt',
     //                array(
     //                    'gte' => \Elastica\Util::convertDate($articleSearch->getDateFrom()->getTimestamp()),
     //                    'lte' => \Elastica\Util::convertDate($articleSearch->getDateTo()->getTimestamp())
     //                )
     //            ));
     //        }
     $boolQuery->addMust(new \Elastica\Query\Range('businessHours.startsAt', array('lte' => 'now')));
     //        $boolQuery->addMust(new \Elastica\Query\Range('businessHours.startsAt',
     //                array(
     //                    //'gte' => \Elastica\Util::convertDate($articleSearch->getDateFrom()->getTimestamp()),
     //                    'lte' => 'now'
     //                ))
     //        );
     //
     // Published or not filter
     if ($placeSearch->getIs24h() !== null && $placeSearch->getIs24h()) {
         //var_dump($placeSearch->getIs24h());die();
         $boolFilter->addMust(new \Elastica\Filter\Term(['is24h' => $placeSearch->getIs24h()]));
         //$boolFilter->addMust('is24h', $placeSearch->getIs24h());
     }
     if ($placeSearch->getIsWifi() !== null && $placeSearch->getIsWifi()) {
         $boolFilter->addMust(new \Elastica\Filter\Term(['isWifi' => $placeSearch->getIsWifi()]));
     }
     if ($placeSearch->getIsDelivery() !== null && $placeSearch->getIsDelivery()) {
         $boolFilter->addMust(new \Elastica\Filter\Term(['isDelivery' => $placeSearch->getIsDelivery()]));
     }
     //$boolFilter->addMust($active);
     //        $boolFilter->addMust(
     //            new \Elastica\Filter\Term(['place.membershipSubscriptions.statusSubscription' => MembershipStatusType::ACTIVE])
     //        );
     //var_dump($boolFilter);die();
     //new \Elastica\Query\
     $filtered = new \Elastica\Query\Filtered($baseQuery, $boolFilter);
     $query = \Elastica\Query::create($filtered);
     $query->addSort(array('place.membershipSubscriptions.membership.score' => array('order' => 'asc')));
     //$query->addSort(array('rating' => array('order' => 'desc')));
     var_dump(json_encode($query->getQuery()));
     die;
     return $this->find($query);
     //$qSort = \Elastica\Query::create($filtered);
     //$query = new \Elastica\Query();
     //$query->setQuery($filtered);
     //$query->setQuery($qSort);
     //$query->setQuery($fnScoreQuery);
     //$fnScoreQuery->setQuery($filtered);
     //$qSort->setQuery($filtered);
     //return $this->find($query);
 }
Пример #9
0
 public function catsucheAction($catid, Request $request)
 {
     $em = $this->getDoctrine()->getManager();
     $mainCat = [];
     $page = 0;
     $pageOffset = 0;
     if ($request->query->get('p')) {
         $page = $request->query->get('p');
         $pageOffset = ($page - 1) * 12;
     }
     $finder = $this->container->get('fos_elastica.finder.search.articles');
     $boolQuery = new \Elastica\Query\BoolQuery();
     if ($request->query->get('q') !== NULL) {
         $searchTerm = $request->query->get('q');
         $fieldQuery = new \Elastica\Query\MultiMatch();
         $fieldQuery->setFields(array('shortName', 'shortDescription', 'longDescription'));
         $fieldQuery->setAnalyzer('custom_search_analyzer');
         $fieldQuery->setOperator('AND');
         $fieldQuery->setQuery($searchTerm);
         $boolQuery->addMust($fieldQuery);
     }
     $categoryQuery = new \Elastica\Query\Terms();
     $categoryQuery->setTerms('catRef', array($catid));
     $boolQuery->addMust($categoryQuery);
     $query = new \Elastica\Query();
     $query->setQuery($boolQuery);
     $query->setSize(10000000);
     $totalpages = ceil(count($finder->find($query)) / 12);
     $query->setSize(12);
     $query->setFrom($pageOffset);
     $articles = $finder->find($query);
     return $this->render('OrthIndexBundle:Shop:kategorien.html.twig', array('articles' => $articles, 'page' => $page, 'totalpages' => $totalpages, 'categories' => $mainCat));
 }
Пример #10
0
 /**
  * Return true if the document exists
  */
 private function documentExists($id, $type)
 {
     $queryTerm = new \Elastica\Query\Terms();
     $queryTerm->setTerms('_id', array($id));
     $elasticaFilterType = new \Elastica\Filter\Type($type);
     $query = Elastica\Query::create($queryTerm);
     $query->setFilter($elasticaFilterType);
     // Perform the search
     $count = $this->elasticaIndex->count($query);
     return $count > 0 ? true : false;
 }
Пример #11
0
 /**
  * Filter search results so only documents that are viewable by the current
  * user will be returned...
  *
  * @param \Elastica\Query\BoolQuery $elasticaQueryBool
  */
 protected function applySecurityFilter($elasticaQueryBool)
 {
     $roles = $this->getCurrentUserRoles();
     $elasticaQueryRoles = new \Elastica\Query\Terms();
     $elasticaQueryRoles->setTerms('view_roles', $roles);
     $elasticaQueryBool->addMust($elasticaQueryRoles);
 }
 /**
  * Create bool query with the fields where you want to look for
  * and the value to look for foreach one
  *
  * @param array $searchFields
  *
  * @return \Elastica\Query\Bool
  */
 protected function getElasticaQuery(array $searchFields)
 {
     $query = new \Elastica\Query\BoolQuery();
     foreach ($searchFields as $fieldName => $searchValue) {
         if (is_array($searchValue)) {
             $query = new \Elastica\Query\Terms($fieldName, $searchValue);
         } else {
             $fieldQuery = new \Elastica\Query\MatchPhrase();
             $fieldQuery->setFieldQuery($fieldName, $searchValue);
             $fieldQuery->setFieldParam($fieldName, 'slop', 1500);
             $query->addShould($fieldQuery);
         }
     }
     return $query;
 }
    protected function doQuery($sourceLanguage, $targetLanguage, $text)
    {
        /* Two query system:
         * 1) Find all strings in source language that match text
         * 2) Do another query for translations for those strings
         */
        $connection = $this->getClient()->getConnection();
        $oldTimeout = $connection->getTimeout();
        $connection->setTimeout(10);
        $fuzzyQuery = new \Elastica\Query\FuzzyLikeThis();
        $fuzzyQuery->setLikeText($text);
        $fuzzyQuery->addFields(array('content'));
        $boostQuery = new \Elastica\Query\FunctionScore();
        if ($this->useWikimediaExtraPlugin()) {
            $boostQuery->addFunction('levenshtein_distance_score', array('text' => $text, 'field' => 'content'));
        } else {
            $groovyScript = <<<GROOVY
import org.apache.lucene.search.spell.*
new LevensteinDistance().getDistance(srctxt, _source['content'])
GROOVY;
            $script = new \Elastica\Script($groovyScript, array('srctxt' => $text), \Elastica\Script::LANG_GROOVY);
            $boostQuery->addScriptScoreFunction($script);
        }
        $boostQuery->setBoostMode(\Elastica\Query\FunctionScore::BOOST_MODE_REPLACE);
        // Wrap the fuzzy query so it can be used as a filter.
        // This is slightly faster, as ES can throw away the scores by this query.
        $fuzzyFilter = new \Elastica\Filter\Query();
        $fuzzyFilter->setQuery($fuzzyQuery);
        $boostQuery->setFilter($fuzzyFilter);
        // Use filtered query to wrap function score and language filter
        $filteredQuery = new \Elastica\Query\Filtered();
        $languageFilter = new \Elastica\Filter\Term();
        $languageFilter->setTerm('language', $sourceLanguage);
        $filteredQuery->setFilter($languageFilter);
        $filteredQuery->setQuery($boostQuery);
        // The whole query
        $query = new \Elastica\Query();
        $query->setQuery($filteredQuery);
        // The interface usually displays three best candidates. These might
        // come from more than three source things, if the translations are
        // the same. In other words suggestions are grouped by the suggested
        // translation. This algorithm might not find all suggestions, if the
        // top N best matching source texts don't have equivalent translations
        // in the target language, but worse matches which we did not fetch do.
        // This code tries to balance between doing too many or too big queries
        // and not fetching enough results to show all possible suggestions.
        $sizeFirst = 100;
        $sizeSecond = $sizeFirst * 5;
        $query->setFrom(0);
        $query->setSize($sizeFirst);
        $query->setParam('_source', array('content'));
        $cutoff = isset($this->config['cutoff']) ? $this->config['cutoff'] : 0.65;
        $query->setParam('min_score', $cutoff);
        $query->setSort(array('_score', '_uid'));
        // This query is doing two unrelated things:
        // 1) Collect the message contents and scores so that they can
        //    be accessed later for the translations we found.
        // 2) Build the query string for the query that fetches the translations.
        $contents = $scores = $terms = array();
        do {
            $resultset = $this->getType()->search($query);
            if (count($resultset) === 0) {
                break;
            }
            foreach ($resultset->getResults() as $result) {
                $data = $result->getData();
                $score = $result->getScore();
                $sourceId = preg_replace('~/[^/]+$~', '', $result->getId());
                $contents[$sourceId] = $data['content'];
                $scores[$sourceId] = $score;
                $terms[] = "{$sourceId}/{$targetLanguage}";
            }
            // Check if it looks like that we are hitting the long tail already.
            // Otherwise, we'll do a query to fetch some more to reach a "sane"
            // breaking point, i.e. include all suggestions with same content
            // for reliable used X times statistics.
            if (count(array_unique($scores)) > 5) {
                break;
            }
            // Okay, We are now in second iteration of the loop. We already got
            // lots of suggestions. We will give up for now even if it means we
            // return in some sense incomplete results.
            if (count($resultset) === $sizeSecond) {
                break;
            }
            // After the first query, the smallest score is the new threshold.
            $query->setParam('min_score', $score);
            $query->setFrom($query->getParam('size') + $query->getParam('from'));
            $query->setSize($sizeSecond);
            // Break if we already got all hits
        } while ($resultset->getTotalHits() > count($contents));
        $suggestions = array();
        // Skip second query if first query found nothing. Keeping only one return
        // statement in this method to avoid forgetting to reset connection timeout
        if ($terms !== array()) {
            $idQuery = new \Elastica\Query\Terms();
            $idQuery->setTerms('_id', $terms);
            $query = new \Elastica\Query($idQuery);
            $query->setSize(25);
            $query->setParam('_source', array('wiki', 'uri', 'content', 'localid'));
            $resultset = $this->getType()->search($query);
            foreach ($resultset->getResults() as $result) {
                $data = $result->getData();
                // Construct the matching source id
                $sourceId = preg_replace('~/[^/]+$~', '', $result->getId());
                $suggestions[] = array('source' => $contents[$sourceId], 'target' => $data['content'], 'context' => $data['localid'], 'quality' => $scores[$sourceId], 'wiki' => $data['wiki'], 'location' => $data['localid'] . '/' . $targetLanguage, 'uri' => $data['uri']);
            }
            // Ensure reults are in quality order
            uasort($suggestions, function ($a, $b) {
                if ($a['quality'] === $b['quality']) {
                    return 0;
                }
                return $a['quality'] < $b['quality'] ? 1 : -1;
            });
        }
        $connection->setTimeout($oldTimeout);
        return $suggestions;
    }