/** * * @param Report $report * @param number $limit * @param string $sort * @param string $order * @param boolean $lazy * @param boolean $active * @param boolean $silent * * @return ArrayCollection $data */ public function generateResults(Report $report, $limit = 0, $sort = '_score', $order = 'desc', $lazy = true, $active = true, $silent = false) { $data = new ArrayCollection(); $request = $this->getServiceLocator()->get('Request'); $silent = $request->getQuery('debug') ? false : $silent; if ($report instanceof Report) { $agent = $report->getAgent(); $lead_query = new \Agent\Elastica\Query\BoolQuery(); if ($active) { $lead_query->addMust(new Elastica\Query\Match('active', 1)); } $client = $this->getElasticaClient(); if ($agent && $client) { $filters = $agent->getFilter(); if ($filters) { $lead_query = $this->applyFilters($lead_query, $filters); } $criteria = $agent->getCriteria(false); if ($criteria) { try { $query = new Elastica\Query(); /* @var $criterion \Agent\Entity\AgentCriterion */ foreach ($criteria as $i => $criterion) { $lead_query = $this->buildQuery($lead_query, $criterion); } $query->setQuery($lead_query); $size = $limit ? $limit : 1000; $query->setParam('track_scores', true); $query->addSort([$sort => ['order' => $order]]); $query->setSize($size); $results = $this->runQuery($query, $lazy, $silent); $total = isset($results['total']) ? $results['total'] : false; if ($total && $results['results']) { foreach ($results['results'] as $result) { $data->add($result); } } if ($total > $size) { $limit = $limit ?: $total; for ($page = 1; $page < ceil($limit / $size); $page++) { $query->setFrom($page * $size); $results = $this->runQuery($query, $silent); if ($results['results']) { foreach ($results as $result) { if (is_array($result)) { foreach ($result as $r) { if ($r instanceof Result) { $data->add($r); } } } elseif ($result instanceof Result) { $data->add($result); } } } } } } catch (\Exception $e) { if (!$silent) { $this->getFlashMessenger()->addErrorMessage($e->getMessage()); } } } } } return $data; }
/** * * @param array $location * * @return Elastica\Query $localityQuery */ public static function getLocalityQuery($location) { $query = new Agent\Elastica\Query\BoolQuery(); $method = 'addMust'; if (!isset($location['state']) && !isset($location['zip']) && !isset($location['locality'])) { foreach (['phone', 'ipaddress'] as $field) { if (isset($location[$field]) && empty($location['state'])) { switch ($field) { case 'ipaddress': $geo = self::$geo; $loc = $geo->getRecord($location['ipaddress']); if ($loc instanceof Record) { $state = $loc->getRegion(); if ($state) { $location['state'] = $state; } } break; case 'phone': $phone = Helper::parse_phonenumber($location['phone'], 'array'); if ($phone) { $state = Helper::area_code_to_state($phone[0]); if ($state) { $location['state'] = $state; } } break; } } } } foreach ($location as $field => $value) { switch ($field) { case 'locality': if (!isset($location['zip'])) { $fields = ['latitude', 'longitude']; $values = is_array($value) ? $value : explode(",", $value); $latlon = count($values) == 2 ? array_combine($fields, $values) : false; if ($latlon) { $path = "location"; $nested = new Elastica\Query\Nested(); $nested->setPath($path); $bool = new Elastica\Query\BoolQuery(); foreach ($latlon as $dim => $coord) { $bool->addMust(new Elastica\Query\Match("{$path}.{$dim}", $coord)); } $nested->setQuery($bool); $query->addMust($nested); } } break; case 'city': if (!isset($location['locality'])) { $query->addShould(new Elastica\Query\Match($field, $value)); } break; case 'state': if (!isset($location['locality'])) { $fields = ['state.abbrev', 'state.full']; $values = is_array($value) ? $value : [$value]; foreach ($values as $state) { $querystring = new Elastica\Query\QueryString($state); $querystring->setFields($fields); $nested = new Elastica\Query\Nested(); $nested->setQuery($querystring); $nested->setPath($field); if (count($values) > 1) { $query->addShould($nested); } else { $query->addMust($nested); } } } break; case 'zip': $query->{$method}(new Elastica\Query\Match($field, $value)); break; } } $localityQuery = new Elastica\Query($query); $localityQuery->setSize(1); return $localityQuery; }
/** * * @param BoolQuery $lead_query * @param AgentCriterion $criterion * * @return BoolQuery $lead_query */ protected function buildQuery(BoolQuery $lead_query, AgentCriterion $criterion) { if (!$criterion->getServiceLocator()) { $criterion->setServiceLocator($this->getServiceLocator()); } $criteria_query = false; $relationship = $criterion->getRelationship(); $required = $criterion->getRequired(); $weight = $criterion->getWeight(); if ($relationship) { $value = $criterion->getValue(); if ($value) { $data = $value->getData(); $boost = $weight ? (1 - $weight) * 10 + 1 : 1; $abstractQuery = $relationship->getQuery(); if ($abstractQuery) { $abstractQuery->setCriterion($criterion); $abstractQuery->setRelationship($relationship); $request = $this->getServiceLocator()->get('Request'); $debug = $request->getQuery('debug'); if ($debug) { echo "<script>console.dir(" . json_encode($data) . ");</script>\n"; } $boolQuery = $abstractQuery->getQuery($data, null, $required, $boost); if ($boolQuery) { switch ($relationship->getType()) { case 'location': $queryClass = (new \ReflectionClass($boolQuery))->getShortName(); switch ($queryClass) { case 'GeoDistance': $criteria_query = $boolQuery; break; default: $criteria_query = new Elastica\Query\HasChild($boolQuery, 'value'); $criteria_query->setParam('score_mode', 'avg'); break; } break; default: $criteria_query = new Elastica\Query\HasChild($boolQuery, 'value'); $criteria_query->setParam('score_mode', 'avg'); break; } if ($required) { $lead_query->addMust($criteria_query); } else { $lead_query->addShould($criteria_query); $lead_query->setBoost($boost); } } } } } return $lead_query; }
/** * * @param mixed $value * @param BoolQuery $query * @param integer|boolean $required * @param integer|float $boost * * @return BoolQuery $query */ public function getQuery($value = null, $query = null, $required = null, $boost = null) { $relationship = $this->getRelationship(); if ($relationship) { $attributeDesc = false; $criterion = $this->getCriterion(); if ($criterion) { $attribute = $criterion->getAttribute(); if ($attribute) { $attributeDesc = $attribute->getAttributeDesc(); } } if ($attributeDesc) { if (!isset($query)) { $query = new BoolQuery(); } $attribute_query = new Elastica\Query\Nested(); $attribute_query->setPath('attribute'); $attribute_query->setQuery(new Elastica\Query\Match('attribute.attributeDesc', $attributeDesc)); $query->addMust($attribute_query); } $this->setQuery($query); } return $this->query; }