Files
Phraseanet/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/QueryContext.php
Mathieu Darse a31442368b Fix number field search
Search with non numeric content will not hit number field (it breaks elasticsearch and is useless anyway)

- Rename QueryHelper::buildPrivateFieldQueries() to wrapPrivateFieldQuery().
    - Signature changed too, the third parameter is dropped an QueryContext is replaced by an array of Field.
    - Query builder closure is now passed an array of Field, not of index field names.
- Remove Field::toConceptPathIndexFieldArray() because method name was beyond understanding (and also because it wasn't needed anymore)
- Various AST node types have changed due to previous API changes
2015-07-23 17:39:11 +02:00

125 lines
3.4 KiB
PHP

<?php
namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\QueryException;
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field;
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Field as ASTField;
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
/**
* @todo Check for private fields and only search on them if allowed
*/
class QueryContext
{
/** @var Structure */
private $structure;
/** @var array */
private $locales;
/** @var string */
private $queryLocale;
/** @var array */
private $fields;
public function __construct(Structure $structure, array $locales, $queryLocale, array $fields = null)
{
$this->structure = $structure;
$this->locales = $locales;
$this->queryLocale = $queryLocale;
$this->fields = $fields;
}
public function narrowToFields(array $fields)
{
if (is_array($this->fields)) {
// Ensure we are not escaping from original fields restrictions
$fields = array_intersect($this->fields, $fields);
if (!$fields) {
throw new QueryException('Query narrowed to non available fields');
}
}
return new static($this->structure, $this->locales, $this->queryLocale, $fields);
}
public function getRawFields()
{
if ($this->fields === null) {
return array('caption_all.raw');
}
$fields = array();
foreach ($this->getUnrestrictedFields() as $field) {
$fields[] = $field->getIndexField(true);
}
return $fields;
}
public function getUnrestrictedFields()
{
// TODO Restore search optimization by using "caption_all" field
// (only when $this->fields is null)
$fields = $this->structure->getUnrestrictedFields();
if ($this->fields !== null) {
$fields = array_intersect_key($fields, array_flip($this->fields));
}
return array_values($fields);
}
public function getPrivateFields()
{
$fields = $this->structure->getPrivateFields();
if ($this->fields !== null) {
$fields = array_intersect_key($fields, array_flip($this->fields));
}
return array_values($fields);
}
public function get($name)
{
if ($name instanceof ASTField) {
$name = $name->getValue();
}
$field = $this->structure->get($name);
if (!$field) {
return null;
}
return $field;
}
/**
* @todo Maybe we should put this logic in Field class?
*/
public function localizeField(Field $field)
{
$index_field = $field->getIndexField();
if ($field->getType() === Mapping::TYPE_STRING) {
return $this->localizeFieldName($index_field);
} else {
return [$index_field];
}
}
private function localizeFieldName($field)
{
$fields = array();
foreach ($this->locales as $locale) {
$boost = ($locale === $this->queryLocale) ? '^5' : '';
$fields[] = sprintf('%s.%s%s', $field, $locale, $boost);
}
// TODO Put generic analyzers on main field instead of "light" sub-field
$fields[] = sprintf('%s.light^10', $field);
return $fields;
}
public function getFields()
{
return $this->fields;
}
}