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:
Mathieu Darse
2015-08-26 19:10:27 +02:00
parent 9d6a428208
commit d6a44c8a52
3 changed files with 64 additions and 69 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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
*