Merge pull request #1472 from jygaulier/PHRAS-668_NBR-FACETS

PHRAS-668
This commit is contained in:
Benoît Burnichon
2015-08-20 11:24:10 +02:00
5 changed files with 66 additions and 8 deletions

View File

@@ -373,7 +373,7 @@ class ElasticSearchEngine implements SearchEngineInterface
]; ];
$query_filters = $this->createQueryFilters($options); $query_filters = $this->createQueryFilters($options);
$acl_filters = $this->createACLFilters(); $acl_filters = $this->createACLFilters($options);
$ESQuery = ['filtered' => ['query' => $ESQuery]]; $ESQuery = ['filtered' => ['query' => $ESQuery]];
@@ -411,13 +411,16 @@ class ElasticSearchEngine implements SearchEngineInterface
// document that shouldn't be displayed can go this far. // document that shouldn't be displayed can go this far.
$agg = []; $agg = [];
$agg['terms']['field'] = $field->getIndexField(true); $agg['terms']['field'] = $field->getIndexField(true);
if(($size = $field->getFacetsSize()) !== null) {
$agg['terms']['size'] = $size;
}
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg); $aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
} }
return $aggs; return $aggs;
} }
private function createACLFilters() private function createACLFilters(SearchEngineOptions $options)
{ {
// No ACLs if no user // No ACLs if no user
if (false === $this->app->getAuthenticator()->isAuthenticated()) { if (false === $this->app->getAuthenticator()->isAuthenticated()) {
@@ -440,7 +443,7 @@ class ElasticSearchEngine implements SearchEngineInterface
// Get intersection between collection ACLs and collection chosen by end user // Get intersection between collection ACLs and collection chosen by end user
$aclRules = $this->getACLsByCollection($flagRules, $flagNamesMap); $aclRules = $this->getACLsByCollection($flagRules, $flagNamesMap);
return $this->buildACLsFilters($aclRules); return $this->buildACLsFilters($aclRules, $options);
} }
private function createQueryFilters(SearchEngineOptions $options) private function createQueryFilters(SearchEngineOptions $options)
@@ -601,11 +604,20 @@ class ElasticSearchEngine implements SearchEngineInterface
return $rules; return $rules;
} }
private function buildACLsFilters(array $aclRules) private function buildACLsFilters(array $aclRules, SearchEngineOptions $options)
{ {
$filters = []; $filters = [];
$collections = $options->getCollections();
$collectionsWoRules = [];
$collectionsWoRules['terms']['base_id'] = [];
foreach ($aclRules as $baseId => $flagsRules) { foreach ($aclRules as $baseId => $flagsRules) {
if(!array_key_exists($baseId, $collections)) {
// no need to add a filter if the collection is not searched
continue;
}
$ruleFilter = $baseFilter = []; $ruleFilter = $baseFilter = [];
// filter on base // filter on base
@@ -626,9 +638,27 @@ class ElasticSearchEngine implements SearchEngineInterface
$ruleFilter['bool']['must'][] = $flagFilter; $ruleFilter['bool']['must'][] = $flagFilter;
} }
$filters[] = $ruleFilter; if(count($ruleFilter['bool']['must']) > 1) {
// some rules found, add the filter
$filters[] = $ruleFilter;
}
else {
// no rules for this collection, add it to the 'simple' list
$collectionsWoRules['terms']['base_id'][] = $baseId;
}
}
if (count($collectionsWoRules['terms']['base_id']) > 0) {
// collections w/o rules : add a simple list ?
if(count($filters) > 0) { // no need to add a big 'should' filter only on collections
$filters[] = $collectionsWoRules;
}
} }
return ['bool' => ['should' => $filters]]; if(count($filters) > 0) {
return ['bool' => ['should' => $filters]];
}
else {
return [];
}
} }
} }

View File

@@ -19,7 +19,8 @@ class Field
private $type; private $type;
private $is_searchable; private $is_searchable;
private $is_private; private $is_private;
private $is_facet; private $is_facet; // bool return facet for this field
private $facets_size; // number of facets to return (null=default, 0= no limit)
private $thesaurus_roots; private $thesaurus_roots;
private $used_by_collections; private $used_by_collections;
@@ -36,10 +37,19 @@ class Field
$roots = null; $roots = null;
} }
// for phraseanet : 0=no facets (also returns isAggregable()=false) ; -1=all facets
$facet = $field->isAggregable();
$facets_size = $field->getAggregableSize();
if($facets_size === -1) {
// for ES 0=all facets
$facets_size = 0;
}
return new self($field->get_name(), $type, [ return new self($field->get_name(), $type, [
'searchable' => $field->is_indexable(), 'searchable' => $field->is_indexable(),
'private' => $field->isBusiness(), 'private' => $field->isBusiness(),
'facet' => $field->isAggregable(), 'facet' => $facet,
'facets_size' => $facets_size,
'thesaurus_roots' => $roots, 'thesaurus_roots' => $roots,
'used_by_collections' => $databox->get_collection_unique_ids() 'used_by_collections' => $databox->get_collection_unique_ids()
]); ]);
@@ -68,6 +78,7 @@ class Field
$this->is_searchable = \igorw\get_in($options, ['searchable'], true); $this->is_searchable = \igorw\get_in($options, ['searchable'], true);
$this->is_private = \igorw\get_in($options, ['private'], false); $this->is_private = \igorw\get_in($options, ['private'], false);
$this->is_facet = \igorw\get_in($options, ['facet'], false); $this->is_facet = \igorw\get_in($options, ['facet'], false);
$this->facets_size = $this->is_facet ? \igorw\get_in($options, ['facets_size'], null) : 0; // here 0 means "no facets"
$this->thesaurus_roots = \igorw\get_in($options, ['thesaurus_roots'], null); $this->thesaurus_roots = \igorw\get_in($options, ['thesaurus_roots'], null);
$this->used_by_collections = \igorw\get_in($options, ['used_by_collections'], []); $this->used_by_collections = \igorw\get_in($options, ['used_by_collections'], []);
@@ -86,6 +97,7 @@ class Field
'searchable' => $this->is_searchable, 'searchable' => $this->is_searchable,
'private' => $this->is_private, 'private' => $this->is_private,
'facet' => $this->is_facet, 'facet' => $this->is_facet,
'facets_size' => $this->facets_size,
'thesaurus_roots' => $this->thesaurus_roots, 'thesaurus_roots' => $this->thesaurus_roots,
'used_by_collections' => $this->used_by_collections 'used_by_collections' => $this->used_by_collections
]); ]);
@@ -171,6 +183,11 @@ class Field
return $this->is_facet; return $this->is_facet;
} }
public function getFacetsSize()
{
return $this->facets_size;
}
public function hasConceptInference() public function hasConceptInference()
{ {
return $this->thesaurus_roots !== null; return $this->thesaurus_roots !== null;

View File

@@ -71,6 +71,9 @@ final class GlobalStructure implements Structure
return $this->private; return $this->private;
} }
/**
* @return Field[]
*/
public function getFacetFields() public function getFacetFields()
{ {
return $this->facets; return $this->facets;

View File

@@ -41,6 +41,9 @@ final class LimitedStructure implements Structure
return $this->limit($this->structure->getPrivateFields()); return $this->limit($this->structure->getPrivateFields());
} }
/**
* @return Field[]
*/
public function getFacetFields() public function getFacetFields()
{ {
return $this->limit($this->structure->getFacetFields()); return $this->limit($this->structure->getFacetFields());

View File

@@ -194,6 +194,11 @@ class databox_field implements cache_cacheableInterface
return $this->aggregable != 0; return $this->aggregable != 0;
} }
public function getAggregableSize()
{
return $this->aggregable;
}
public function hydrate(Application $app) public function hydrate(Application $app)
{ {
$this->app = $app; $this->app = $app;