/** * Reset sphinx client and apply the options * * Only apply filters and group by * * @param SearchEngineOptions $options * @return SphinxSearch */ protected function applyOptions(SearchEngineOptions $options) { $this->resetSphinx(); $filters = []; foreach ($options->getCollections() as $collection) { $filters[] = sprintf("%u", crc32($collection->get_databox()->get_sbas_id() . '_' . $collection->get_coll_id())); } $this->sphinx->SetFilter('crc_sbas_coll', $filters); $this->sphinx->SetFilter('deleted', [0]); $this->sphinx->SetFilter('parent_record_id', [$options->getSearchType()]); if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) { foreach (array_unique(array_map(function (\databox_field $field) { return $field->get_name(); }, $options->getDateFields())) as $field) { $min = $options->getMinDate() ? $options->getMinDate()->format('U') : 0; $max = $options->getMaxDate() ? $options->getMaxDate()->format('U') : pow(2, 32); $this->sphinx->SetFilterRange(ConfigurationPanel::DATE_FIELD_PREFIX . $field, $min, $max); } } if ($options->getFields()) { $filters = []; foreach ($options->getFields() as $field) { $filters[] = sprintf("%u", crc32($field->get_databox()->get_sbas_id() . '_' . $field->get_id())); } $this->sphinx->SetFilter('crc_struct_id', $filters); } if ($options->getBusinessFieldsOn()) { $crc_coll_business = []; foreach ($options->getBusinessFieldsOn() as $collection) { $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_1')); $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_0')); } $non_business = []; foreach ($options->getCollections() as $collection) { foreach ($options->getBusinessFieldsOn() as $BFcollection) { if ($collection->get_base_id() == $BFcollection->get_base_id()) { continue 2; } } $non_business[] = $collection; } foreach ($non_business as $collection) { $crc_coll_business[] = sprintf("%u", crc32($collection->get_coll_id() . '_0')); } $this->sphinx->SetFilter('crc_coll_business', $crc_coll_business); } elseif ($options->getFields()) { $this->sphinx->SetFilter('business', [0]); } /** * @todo : enhance : check status in a better way */ $status_opts = $options->getStatus(); foreach ($options->getDataboxes() as $databox) { foreach ($databox->get_statusbits() as $n => $status) { if (!array_key_exists($n, $status_opts)) { continue; } if (!array_key_exists($databox->get_sbas_id(), $status_opts[$n])) { continue; } $crc = sprintf("%u", crc32($databox->get_sbas_id() . '_' . $n)); $this->sphinx->SetFilter('status', [$crc], $status_opts[$n][$databox->get_sbas_id()] == '0'); } } if ($options->getRecordType()) { $this->sphinx->SetFilter('crc_type', [sprintf("%u", crc32($options->getRecordType()))]); } $order = ''; switch ($options->getSortOrder()) { case SearchEngineOptions::SORT_MODE_ASC: $order = 'ASC'; break; case SearchEngineOptions::SORT_MODE_DESC: default: $order = 'DESC'; break; } switch ($options->getSortBy()) { case SearchEngineOptions::SORT_RANDOM: $sort = '@random'; break; case SearchEngineOptions::SORT_RELEVANCE: default: $sort = '@relevance ' . $order . ', created_on ' . $order; break; case SearchEngineOptions::SORT_CREATED_ON: $sort = 'created_on ' . $order; break; } $this->sphinx->SetGroupBy('crc_sbas_record', SPH_GROUPBY_ATTR, $sort); return $this; }
/** * {@inheritdoc} */ public function query($query, $offset, $perPage, SearchEngineOptions $options = null) { if (null === $options) { $options = new SearchEngineOptions(); } $this->initialize(); $this->checkSession(); $this->clearAllCache(new \DateTime('-1 hour')); assert(is_int($offset)); assert($offset >= 0); assert(is_int($perPage)); if (trim($query) === '') { $query = "all"; } if ($options->getRecordType()) { $query .= ' AND recordtype=' . $options->getRecordType(); } $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id'; $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); $stmt->execute([':ses_id' => $this->app['session']->get('phrasea_session_id')]); $row = $stmt->fetch(\PDO::FETCH_ASSOC); $stmt->closeCursor(); $date_obj = new \DateTime('-10 min'); $date_quest = new \DateTime($row['query_time']); if ($query != $row['query']) { $this->resetCacheNextQuery = true; } if ($date_obj > $date_quest) { $this->resetCacheNextQuery = true; } if ($this->resetCacheNextQuery === true) { phrasea_clear_cache($this->app['session']->get('phrasea_session_id')); $this->addQuery($query, $options); $this->executeQuery($query, $options); $sql = 'SELECT query, query_time, duration, total FROM cache WHERE session_id = :ses_id'; $stmt = $this->app['phraseanet.appbox']->get_connection()->prepare($sql); $stmt->execute([':ses_id' => $this->app['session']->get('phrasea_session_id')]); $row = $stmt->fetch(\PDO::FETCH_ASSOC); $stmt->closeCursor(); } else { /** * @todo clean this in DB */ $this->total_available = $this->total_results = $this->app['session']->get('phrasea_engine_n_results'); } $res = phrasea_fetch_results($this->app['session']->get('phrasea_session_id'), $offset + 1, $perPage, false); $rs = []; $error = $this->app->trans('Unable to execute query'); if (isset($res['results']) && is_array($res['results'])) { $rs = $res['results']; $error = ''; } $resultNumber = $offset; $records = new ArrayCollection(); foreach ($rs as $data) { try { $records->add(new \record_adapter($this->app, \phrasea::sbasFromBas($this->app, $data['base_id']), $data['record_id'], $resultNumber)); } catch (\Exception $e) { } $resultNumber++; } $propositions = $this->getPropositions(); $suggestions = $this->getSuggestions($query); return new SearchEngineResult($records, $query, $row['duration'], $offset, $row['total'], $row['total'], $error, '', $suggestions, $propositions, ''); }
private function createFilters(SearchEngineOptions $options) { $filters = []; $status_opts = $options->getStatus(); foreach ($options->getDataboxes() as $databox) { foreach ($databox->get_statusbits() as $n => $status) { if (!array_key_exists($n, $status_opts)) { continue; } if (!array_key_exists($databox->get_sbas_id(), $status_opts[$n])) { continue; } $filters[] = ['term' => ['status.status-' . $n => $status_opts[$n][$databox->get_sbas_id()]]]; } } $filters[] = ['terms' => ['base_id' => array_map(function (\collection $coll) { return $coll->get_base_id(); }, $options->getCollections())]]; $filters[] = ['term' => ['type' => $options->getSearchType() === SearchEngineOptions::RECORD_RECORD ? 'record' : 'story']]; if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) { $range = []; if ($options->getMaxDate()) { $range['lte'] = $options->getMaxDate()->format(DATE_ATOM); } if ($options->getMinDate()) { $range['gte'] = $options->getMinDate()->format(DATE_ATOM); } foreach ($options->getDateFields() as $dateField) { $filters[] = ['range' => ['caption.' . $dateField->get_name() => $range]]; } } if ($options->getRecordType()) { $filters[] = ['term' => ['phrasea_type' => $options->getRecordType()]]; } return $filters; }
private function createQueryFilters(SearchEngineOptions $options) { $filters = []; $filters[]['term']['record_type'] = $options->getSearchType() === SearchEngineOptions::RECORD_RECORD ? SearchEngineInterface::GEM_TYPE_RECORD : SearchEngineInterface::GEM_TYPE_STORY; if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) { $range = []; if ($options->getMaxDate()) { $range['lte'] = $options->getMaxDate()->format(Mapping::DATE_FORMAT_CAPTION_PHP); } if ($options->getMinDate()) { $range['gte'] = $options->getMinDate()->format(Mapping::DATE_FORMAT_CAPTION_PHP); } foreach ($options->getDateFields() as $dateField) { $filters[]['range']['caption.' . $dateField->get_name()] = $range; } } if ($type = $options->getRecordType()) { $filters[]['term']['type'] = $type; } $collections = $options->getCollections(); if (count($collections) > 0) { $filters[]['terms']['base_id'] = array_keys($collections); } if (count($options->getStatus()) > 0) { $status_filters = []; $flagNamesMap = $this->getFlagsKey($this->app['phraseanet.appbox']); foreach ($options->getStatus() as $databoxId => $status) { $status_filter = $databox_status = []; $status_filter[] = ['term' => ['databox_id' => $databoxId]]; foreach ($status as $n => $v) { if (!isset($flagNamesMap[$databoxId][$n])) { continue; } $label = $flagNamesMap[$databoxId][$n]; $databox_status[] = ['term' => [sprintf('flags.%s', $label) => (bool) $v]]; } $status_filter[] = $databox_status; $status_filters[] = ['bool' => ['must' => $status_filter]]; } $filters[]['bool']['should'] = $status_filters; } return $filters; }