mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-17 15:03:25 +00:00
Lower-level API to build concept queries
Removes wrapPrivateFieldConceptQueries(). The goal is to wrap text and concept queries with a single call to wrapPrivateFieldQueries().
This commit is contained in:
@@ -13,6 +13,7 @@ abstract class AbstractTermNode extends Node implements TermInterface
|
||||
protected $text;
|
||||
protected $context;
|
||||
private $concepts = [];
|
||||
private $pruned_concepts;
|
||||
|
||||
public function __construct($text, Context $context = null)
|
||||
{
|
||||
@@ -22,56 +23,70 @@ abstract class AbstractTermNode extends Node implements TermInterface
|
||||
|
||||
public function setConcepts(array $concepts)
|
||||
{
|
||||
$this->pruned_concepts = null;
|
||||
$this->concepts = $concepts;
|
||||
}
|
||||
|
||||
private function getPrunedConcepts()
|
||||
{
|
||||
if ($this->pruned_concepts === null) {
|
||||
$this->pruned_concepts = Concept::pruneNarrowConcepts($this->concepts);
|
||||
}
|
||||
return $this->pruned_concepts;
|
||||
}
|
||||
|
||||
protected function buildConceptQueries(QueryContext $context)
|
||||
{
|
||||
$concepts = Concept::pruneNarrowConcepts($this->concepts);
|
||||
if (!$concepts) {
|
||||
if (!$this->getPrunedConcepts()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query_builder = function (array $fields) use ($concepts) {
|
||||
$index_fields = [];
|
||||
foreach ($fields as $field) {
|
||||
$index_fields[] = $field->getConceptPathIndexField();
|
||||
}
|
||||
if (!$index_fields) {
|
||||
return null;
|
||||
}
|
||||
$query_builder = function (array $fields) {
|
||||
$concept_queries = $this->buildConceptQueriesForFields($fields);
|
||||
$query = null;
|
||||
foreach ($concepts as $concept) {
|
||||
$concept_query = [
|
||||
'multi_match' => [
|
||||
'fields' => $index_fields,
|
||||
'query' => $concept->getPath()
|
||||
]
|
||||
];
|
||||
foreach ($concept_queries as $concept_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
||||
}
|
||||
return $query;
|
||||
};
|
||||
|
||||
$query = $query_builder($context->getUnrestrictedFields());
|
||||
if (
|
||||
isset($query['bool']) &&
|
||||
isset($query['bool']['should']) &&
|
||||
count($query) === 1 /* no options or must(_not) clauses */
|
||||
) {
|
||||
$queries = $query['bool']['should'];
|
||||
} else {
|
||||
$queries = [$query];
|
||||
}
|
||||
$queries = $this->buildConceptQueriesForFields($context->getUnrestrictedFields());
|
||||
|
||||
$private_fields = $context->getPrivateFields();
|
||||
foreach (QueryHelper::wrapPrivateFieldConceptQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
$queries[] = $private_field_query;
|
||||
}
|
||||
|
||||
return $queries;
|
||||
}
|
||||
|
||||
protected function buildConceptQueriesForFields(array $fields)
|
||||
{
|
||||
$concepts = $this->getPrunedConcepts();
|
||||
if (!$concepts) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$index_fields = [];
|
||||
foreach ($fields as $field) {
|
||||
$index_fields[] = $field->getConceptPathIndexField();
|
||||
}
|
||||
if (!$index_fields) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$queries = [];
|
||||
foreach ($concepts as $concept) {
|
||||
$queries[] = [
|
||||
'multi_match' => [
|
||||
'fields' => $index_fields,
|
||||
'query' => $concept->getPath()
|
||||
]
|
||||
];
|
||||
}
|
||||
return $queries;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->text;
|
||||
|
@@ -59,19 +59,31 @@ class TextNode extends AbstractTermNode implements ContextAbleInterface
|
||||
};
|
||||
|
||||
$unrestricted_fields = $context->getUnrestrictedFields();
|
||||
$unrestricted_fields = Field::filterByValueCompatibility($unrestricted_fields, $this->text);
|
||||
$query = $query_builder($unrestricted_fields);
|
||||
$compatible_unrestricted_fields = Field::filterByValueCompatibility($unrestricted_fields, $this->text);
|
||||
$query = $query_builder($compatible_unrestricted_fields);
|
||||
|
||||
$private_fields = $context->getPrivateFields();
|
||||
$private_fields = Field::filterByValueCompatibility($private_fields, $this->text);
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
$compatible_private_fields = Field::filterByValueCompatibility($private_fields, $this->text);
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($compatible_private_fields, $query_builder) as $private_field_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $private_field_query);
|
||||
}
|
||||
|
||||
$concept_queries = $this->buildConceptQueries($context);
|
||||
// Concepts handling
|
||||
$concept_queries = $this->buildConceptQueriesForFields($unrestricted_fields);
|
||||
foreach ($concept_queries as $concept_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
||||
}
|
||||
$query_builder = function (array $fields) {
|
||||
$concept_queries = $this->buildConceptQueriesForFields($fields);
|
||||
$query = null;
|
||||
foreach ($concept_queries as $concept_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
||||
}
|
||||
return $query;
|
||||
};
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $private_field_query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
@@ -29,10 +29,10 @@ class QueryHelper
|
||||
foreach ($fields_map as $hash => $fields) {
|
||||
// Right to query on a private field is dependant of document collection
|
||||
// Here we make sure we can only match on allowed collections
|
||||
$queries[] = self::restrictQueryToCollections(
|
||||
$query_builder($fields),
|
||||
$collections_map[$hash]
|
||||
);
|
||||
$query = $query_builder($fields);
|
||||
if ($query !== null) {
|
||||
$queries[] = self::restrictQueryToCollections($query, $collections_map[$hash]);
|
||||
}
|
||||
}
|
||||
|
||||
return $queries;
|
||||
@@ -61,38 +61,6 @@ class QueryHelper
|
||||
return implode('|', $collections);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Factor with wrapPrivateFieldQueries()
|
||||
*/
|
||||
public static function wrapPrivateFieldConceptQueries(array $fields, \Closure $query_builder)
|
||||
{
|
||||
// We make a boolean clause for each collection set to shrink query size
|
||||
// (instead of a clause for each field, with his collection set)
|
||||
$fields_map = [];
|
||||
$collections_map = [];
|
||||
foreach ($fields as $field) {
|
||||
$collections = $field->getDependantCollections();
|
||||
$hash = self::hashCollections($collections);
|
||||
$collections_map[$hash] = $collections;
|
||||
if (!isset($fields_map[$hash])) {
|
||||
$fields_map[$hash] = [];
|
||||
}
|
||||
// Merge fields with others having the same collections
|
||||
$fields_map[$hash][] = $field;
|
||||
}
|
||||
|
||||
$queries = [];
|
||||
foreach ($fields_map as $hash => $fields) {
|
||||
// Right to query on a private field is dependant of document collection
|
||||
// Here we make sure we can only match on allowed collections
|
||||
$query = $query_builder($fields);
|
||||
$query = self::restrictQueryToCollections($query, $collections_map[$hash]);
|
||||
$queries[] = $query;
|
||||
}
|
||||
|
||||
return $queries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply conjunction or disjunction between a query and a sub query clause
|
||||
*
|
||||
|
Reference in New Issue
Block a user