PHRAS-676 #time 3h

new : returns facet on "type" (image, video, ...)
new : query on pseudo-field "type", ex:  "type:image"
This commit is contained in:
Jean-Yves Gaulier
2015-09-04 14:34:25 +02:00
parent 2643d697c2
commit e8f61a443b
7 changed files with 530 additions and 472 deletions

View File

@@ -29,6 +29,7 @@
// Rest // Rest
%token database database %token database database
%token collection collection %token collection collection
%token type type
%token id id|recordid %token id id|recordid
%token word [^\s()\[\]:<>≤≥=]+ %token word [^\s()\[\]:<>≤≥=]+
@@ -55,6 +56,7 @@ ternary:
quaternary: quaternary:
::database:: ::colon:: string() #database ::database:: ::colon:: string() #database
| ::collection:: ::colon:: string() #collection | ::collection:: ::colon:: string() #collection
| ::type:: ::colon:: string() #type
| ::id:: ::colon:: string() #id | ::id:: ::colon:: string() #id
| quinary() | quinary()
@@ -136,6 +138,7 @@ keyword:
| <or> | <or>
| <database> | <database>
| <collection> | <collection>
| <type>
| <id> | <id>
symbol: symbol:

View File

@@ -0,0 +1,34 @@
<?php
namespace Alchemy\Phrasea\SearchEngine\Elastic\AST;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
class TypeExpression extends Node
{
private $typeName;
public function __construct($typeName)
{
$this->typeName = $typeName;
}
public function buildQuery(QueryContext $context)
{
return [
'term' => [
'type' => $this->typeName
]
];
}
public function getTermNodes()
{
return array();
}
public function __toString()
{
return sprintf('<type:%s>', $this->typeName);
}
}

View File

@@ -444,6 +444,11 @@ class ElasticSearchEngine implements SearchEngineInterface
$base_facet_agg['terms']['field'] = 'databox_name'; $base_facet_agg['terms']['field'] = 'databox_name';
$aggs['Base'] = $base_facet_agg; $aggs['Base'] = $base_facet_agg;
// We always want a type facet right now
$base_facet_agg = array();
$base_facet_agg['terms']['field'] = 'type';
$aggs['Type'] = $base_facet_agg;
$structure = $this->getLimitedStructure($options); $structure = $this->getLimitedStructure($options);
foreach ($structure->getFacetFields() as $name => $field) { foreach ($structure->getFacetFields() as $name => $field) {
// 2015-05-26 (mdarse) Removed databox filtering. // 2015-05-26 (mdarse) Removed databox filtering.

View File

@@ -441,72 +441,72 @@ class QueryParser
function parserPerformAction(&$thisS, &$yy, $yystate, &$s, $o) function parserPerformAction(&$thisS, &$yy, $yystate, &$s, $o)
{ {
/* this == yyval */ /* this == yyval */
switch ($yystate) { switch ($yystate) {
case 1: case 1:
return $thisS; return $thisS;
break; break;
case 2: case 2:
// $thisS = sprintf('(%s DEF_OP %s)', $s[$o-1]->text, $s[$o]->text); // $thisS = sprintf('(%s DEF_OP %s)', $s[$o-1]->text, $s[$o]->text);
$thisS = new AST\AndExpression($s[$o-1]->text, $s[$o]->text); $thisS = new AST\AndExpression($s[$o-1]->text, $s[$o]->text);
break; break;
case 4: case 4:
$thisS = new AST\AndExpression($s[$o-2]->text, $s[$o]->text); $thisS = new AST\AndExpression($s[$o-2]->text, $s[$o]->text);
break; break;
case 5: case 5:
$thisS = new AST\OrExpression($s[$o-2]->text, $s[$o]->text); $thisS = new AST\OrExpression($s[$o-2]->text, $s[$o]->text);
break; break;
case 6: case 6:
$thisS = new AST\InExpression($s[$o]->text, $s[$o-2]->text); $thisS = new AST\InExpression($s[$o]->text, $s[$o-2]->text);
break; break;
case 7: case 7:
$thisS = $s[$o-1]; $thisS = $s[$o-1];
break; break;
case 10: case 10:
$thisS = new AST\KeywordNode($s[$o]->text); $thisS = new AST\KeywordNode($s[$o]->text);
break; break;
case 11: case 11:
$thisS = new AST\PrefixNode($s[$o-1]->text); $thisS = new AST\PrefixNode($s[$o-1]->text);
break; break;
case 12: case 12:
$thisS = new AST\TextNode($s[$o]->text); $thisS = new AST\TextNode($s[$o]->text);
break; break;
case 13: case 13:
$thisS = new AST\QuotedTextNode($s[$o]->text); $thisS = new AST\QuotedTextNode($s[$o]->text);
break; break;
} }
} }
@@ -907,49 +907,49 @@ break;
function LexerPerformAction($avoidingNameCollisions, $YY_START = null) function LexerPerformAction($avoidingNameCollisions, $YY_START = null)
{ {
; ;
switch($avoidingNameCollisions) { switch($avoidingNameCollisions) {
case 0:/* skip whitespace */ case 0:/* skip whitespace */
break; break;
case 1:return 7; case 1:return 7;
break; break;
case 2:return 7; case 2:return 7;
break; break;
case 3:return 7; case 3:return 7;
break; break;
case 4:return 8; case 4:return 8;
break; break;
case 5:return 8; case 5:return 8;
break; break;
case 6:return 8; case 6:return 8;
break; break;
case 7:return 9; case 7:return 9;
break; break;
case 8:return 9; case 8:return 9;
break; break;
case 9:return 9; case 9:return 9;
break; break;
case 10:return 11; case 10:return 11;
break; break;
case 11:return 12; case 11:return 12;
break; break;
case 12:return 16; case 12:return 16;
break; break;
case 13: case 13:
$this->begin('literal'); $this->begin('literal');
break; break;
case 14: case 14:
$this->popState(); $this->popState();
break; break;
case 15:return 17; case 15:return 17;
break; break;
case 16:return 15; case 16:return 15;
break; break;
case 17:return 5; case 17:return 5;
break; break;
} }
} }
} }

View File

@@ -75,6 +75,8 @@ class FacetsResponse implements JsonSerializable
return sprintf('collection:%s', $this->escaper->escapeWord($value)); return sprintf('collection:%s', $this->escaper->escapeWord($value));
case 'Base': case 'Base':
return sprintf('database:%s', $this->escaper->escapeWord($value)); return sprintf('database:%s', $this->escaper->escapeWord($value));
case 'Type':
return sprintf('type:%s', $this->escaper->escapeWord($value));
default: default:
return sprintf('r"%s" IN %s', $this->escaper->escapeRaw($value), $name); return sprintf('r"%s" IN %s', $this->escaper->escapeRaw($value), $name);
} }

View File

@@ -22,6 +22,7 @@ class NodeTypes
const TEXT = '#text'; const TEXT = '#text';
const CONTEXT = '#context'; const CONTEXT = '#context';
const COLLECTION = '#collection'; const COLLECTION = '#collection';
const TYPE = '#type';
const DATABASE = '#database'; const DATABASE = '#database';
const IDENTIFIER = '#id'; const IDENTIFIER = '#id';
// Token types for leaf nodes // Token types for leaf nodes

View File

@@ -88,6 +88,9 @@ class QueryVisitor implements Visit
case NodeTypes::COLLECTION: case NodeTypes::COLLECTION:
return $this->visitCollectionNode($element); return $this->visitCollectionNode($element);
case NodeTypes::TYPE:
return $this->visitTypeNode($element);
case NodeTypes::IDENTIFIER: case NodeTypes::IDENTIFIER:
return $this->visitIdentifierNode($element); return $this->visitIdentifierNode($element);
@@ -279,6 +282,16 @@ class QueryVisitor implements Visit
return new AST\CollectionExpression($collectionName); return new AST\CollectionExpression($collectionName);
} }
private function visitTypeNode(Element $element)
{
if ($element->getChildrenNumber() !== 1) {
throw new \Exception('Type filter can only have a single child.');
}
$typeName = $element->getChild(0)->getValue()['value'];
return new AST\TypeExpression($typeName);
}
private function visitIdentifierNode(Element $element) private function visitIdentifierNode(Element $element)
{ {
if ($element->getChildrenNumber() !== 1) { if ($element->getChildrenNumber() !== 1) {