mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +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 $text;
|
||||||
protected $context;
|
protected $context;
|
||||||
private $concepts = [];
|
private $concepts = [];
|
||||||
|
private $pruned_concepts;
|
||||||
|
|
||||||
public function __construct($text, Context $context = null)
|
public function __construct($text, Context $context = null)
|
||||||
{
|
{
|
||||||
@@ -22,56 +23,70 @@ abstract class AbstractTermNode extends Node implements TermInterface
|
|||||||
|
|
||||||
public function setConcepts(array $concepts)
|
public function setConcepts(array $concepts)
|
||||||
{
|
{
|
||||||
|
$this->pruned_concepts = null;
|
||||||
$this->concepts = $concepts;
|
$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)
|
protected function buildConceptQueries(QueryContext $context)
|
||||||
{
|
{
|
||||||
$concepts = Concept::pruneNarrowConcepts($this->concepts);
|
if (!$this->getPrunedConcepts()) {
|
||||||
if (!$concepts) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$query_builder = function (array $fields) use ($concepts) {
|
$query_builder = function (array $fields) {
|
||||||
$index_fields = [];
|
$concept_queries = $this->buildConceptQueriesForFields($fields);
|
||||||
foreach ($fields as $field) {
|
|
||||||
$index_fields[] = $field->getConceptPathIndexField();
|
|
||||||
}
|
|
||||||
if (!$index_fields) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$query = null;
|
$query = null;
|
||||||
foreach ($concepts as $concept) {
|
foreach ($concept_queries as $concept_query) {
|
||||||
$concept_query = [
|
|
||||||
'multi_match' => [
|
|
||||||
'fields' => $index_fields,
|
|
||||||
'query' => $concept->getPath()
|
|
||||||
]
|
|
||||||
];
|
|
||||||
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
||||||
}
|
}
|
||||||
return $query;
|
return $query;
|
||||||
};
|
};
|
||||||
|
|
||||||
$query = $query_builder($context->getUnrestrictedFields());
|
$queries = $this->buildConceptQueriesForFields($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];
|
|
||||||
}
|
|
||||||
|
|
||||||
$private_fields = $context->getPrivateFields();
|
$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;
|
$queries[] = $private_field_query;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $queries;
|
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()
|
public function getValue()
|
||||||
{
|
{
|
||||||
return $this->text;
|
return $this->text;
|
||||||
|
@@ -59,19 +59,31 @@ class TextNode extends AbstractTermNode implements ContextAbleInterface
|
|||||||
};
|
};
|
||||||
|
|
||||||
$unrestricted_fields = $context->getUnrestrictedFields();
|
$unrestricted_fields = $context->getUnrestrictedFields();
|
||||||
$unrestricted_fields = Field::filterByValueCompatibility($unrestricted_fields, $this->text);
|
$compatible_unrestricted_fields = Field::filterByValueCompatibility($unrestricted_fields, $this->text);
|
||||||
$query = $query_builder($unrestricted_fields);
|
$query = $query_builder($compatible_unrestricted_fields);
|
||||||
|
|
||||||
$private_fields = $context->getPrivateFields();
|
$private_fields = $context->getPrivateFields();
|
||||||
$private_fields = Field::filterByValueCompatibility($private_fields, $this->text);
|
$compatible_private_fields = Field::filterByValueCompatibility($private_fields, $this->text);
|
||||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
foreach (QueryHelper::wrapPrivateFieldQueries($compatible_private_fields, $query_builder) as $private_field_query) {
|
||||||
$query = QueryHelper::applyBooleanClause($query, 'should', $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) {
|
foreach ($concept_queries as $concept_query) {
|
||||||
$query = QueryHelper::applyBooleanClause($query, 'should', $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;
|
return $query;
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,10 @@ class QueryHelper
|
|||||||
foreach ($fields_map as $hash => $fields) {
|
foreach ($fields_map as $hash => $fields) {
|
||||||
// Right to query on a private field is dependant of document collection
|
// Right to query on a private field is dependant of document collection
|
||||||
// Here we make sure we can only match on allowed collections
|
// Here we make sure we can only match on allowed collections
|
||||||
$queries[] = self::restrictQueryToCollections(
|
$query = $query_builder($fields);
|
||||||
$query_builder($fields),
|
if ($query !== null) {
|
||||||
$collections_map[$hash]
|
$queries[] = self::restrictQueryToCollections($query, $collections_map[$hash]);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $queries;
|
return $queries;
|
||||||
@@ -61,38 +61,6 @@ class QueryHelper
|
|||||||
return implode('|', $collections);
|
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
|
* Apply conjunction or disjunction between a query and a sub query clause
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user