Handle search with on timestamp

PHRAS-689
This commit is contained in:
Mathieu Darse
2015-11-10 18:36:29 +01:00
parent 5dc1fbe2cb
commit 0cd9933ac6
7 changed files with 92 additions and 6 deletions

View File

@@ -30,6 +30,8 @@
%token collection collection
%token type type
%token id id|recordid
%token created_on created_(on|at)
%token updated_on updated_(on|at)
%token field_prefix field\.
%token flag_prefix flag\.
%token meta_prefix (?:meta|exif)\.
@@ -89,10 +91,15 @@ match_key:
| <id>
key:
::meta_prefix:: meta_key()
timestamp_key()
| ::meta_prefix:: meta_key()
| ::field_prefix:: field_key()
| field_key()
#timestamp_key:
<created_on>
| <updated_on>
#meta_key:
word_or_keyword()+
@@ -164,6 +171,8 @@ keyword:
| <collection>
| <type>
| <id>
| <created_on>
| <updated_on>
| <field_prefix>
| <flag_prefix>
| <meta_prefix>

View File

@@ -0,0 +1,42 @@
<?php
namespace Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue;
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
class TimestampKey implements Key
{
private $type;
private $index_field;
public static function createdOn()
{
return new self('creation', 'created_on');
}
public static function updatedOn()
{
return new self('update', 'updated_on');
}
private function __construct($type, $index_field)
{
$this->type = $type;
$this->index_field = $index_field;
}
public function getIndexField(QueryContext $context, $raw = false)
{
return $this->index_field;
}
public function isValueCompatible($value, QueryContext $context)
{
return true;
}
public function __toString()
{
return $this->type;
}
}

View File

@@ -302,8 +302,8 @@ class RecordIndexer
->add('type', 'string')->notAnalyzed()
->add('record_type', 'string')->notAnalyzed() // record or story
// Dates
->add('created_on', 'date')->format(Mapping::DATE_FORMAT_MYSQL)
->add('updated_on', 'date')->format(Mapping::DATE_FORMAT_MYSQL)
->add('created_on', 'date')->format(Mapping::DATE_FORMAT_MYSQL_OR_CAPTION)
->add('updated_on', 'date')->format(Mapping::DATE_FORMAT_MYSQL_OR_CAPTION)
// Thesaurus
->add('concept_path', $this->getThesaurusPathMapping())
// EXIF

View File

@@ -22,6 +22,7 @@ class Mapping
const DATE_FORMAT_MYSQL = 'yyyy-MM-dd HH:mm:ss';
const DATE_FORMAT_CAPTION = 'yyyy/MM/dd'; // ES format
const DATE_FORMAT_MYSQL_OR_CAPTION = 'yyyy-MM-dd HH:mm:ss||yyyy/MM/dd';
const DATE_FORMAT_CAPTION_PHP = 'Y/m/d'; // PHP format
// Core types

View File

@@ -27,6 +27,7 @@ class NodeTypes
const FLAG_STATEMENT = '#flag_statement';
const FLAG = '#flag';
const NATIVE_KEY = '#native_key';
const TIMESTAMP_KEY = '#timestamp_key';
// Token types for leaf nodes
const TOKEN_WORD = 'word';
const TOKEN_QUOTED_STRING = 'quoted';
@@ -35,6 +36,8 @@ class NodeTypes
const TOKEN_COLLECTION = 'collection';
const TOKEN_MEDIA_TYPE = 'type';
const TOKEN_RECORD_ID = 'id';
const TOKEN_CREATED_ON = 'created_on';
const TOKEN_UPDATED_ON = 'updated_on';
const TOKEN_TRUE = 'true';
const TOKEN_FALSE = 'false';
}

View File

@@ -95,6 +95,9 @@ class QueryVisitor implements Visit
case NodeTypes::NATIVE_KEY:
return $this->visitNativeKeyNode($element);
case NodeTypes::TIMESTAMP_KEY:
return $this->visitTimestampKeyNode($element);
case NodeTypes::METADATA_KEY:
return new AST\KeyValue\MetadataKey($this->visitString($element));
@@ -297,10 +300,10 @@ class QueryVisitor implements Visit
});
}
private function visitNativeKeyNode(Element $element)
private function visitNativeKeyNode(TreeNode $node)
{
$this->assertChildrenCount($element, 1);
$type = $element->getChild(0)->getValue()['token'];
$this->assertChildrenCount($node, 1);
$type = $node->getChild(0)->getValue()['token'];
switch ($type) {
case NodeTypes::TOKEN_DATABASE:
return AST\KeyValue\NativeKey::database();
@@ -315,6 +318,20 @@ class QueryVisitor implements Visit
}
}
private function visitTimestampKeyNode(TreeNode $node)
{
$this->assertChildrenCount($node, 1);
$type = $node->getChild(0)->getValue()['token'];
switch ($type) {
case NodeTypes::TOKEN_CREATED_ON:
return AST\KeyValue\TimestampKey::createdOn();
case NodeTypes::TOKEN_UPDATED_ON:
return AST\KeyValue\TimestampKey::updatedOn();
default:
throw new InvalidArgumentException(sprintf('Unexpected token type "%s" for timestamp key.', $type));
}
}
private function assertChildrenCount(TreeNode $node, $count)
{
if ($node->getChildrenNumber() !== $count) {

View File

@@ -93,6 +93,20 @@ id:90 AND foo|(<record_identifier:"90"> AND <text:"foo">)
id:90 foo|(<record_identifier:"90"> AND <text:"foo">)
recordid:90|<record_identifier:"90">
# Timestamps
created_on < "2015/01/01"|<range:creation lt="2015/01/01">
created_on ≤ "2015/01/01"|<range:creation lte="2015/01/01">
created_on = "2015/01/01"|(<creation> == <value:"2015/01/01">)
created_on ≥ "2015/01/01"|<range:creation gte="2015/01/01">
created_on > "2015/01/01"|<range:creation gt="2015/01/01">
updated_on < "2015/01/01"|<range:update lt="2015/01/01">
updated_on ≤ "2015/01/01"|<range:update lte="2015/01/01">
updated_on = "2015/01/01"|(<update> == <value:"2015/01/01">)
updated_on ≥ "2015/01/01"|<range:update gte="2015/01/01">
updated_on > "2015/01/01"|<range:update gt="2015/01/01">
created_at > "2015/01/01"|<range:creation gt="2015/01/01">
updated_at > "2015/01/01"|<range:update gt="2015/01/01">
# Flag matcher
flag.foo:true|<flag:foo set>
flag.foo:1|<flag:foo set>
Can't render this file because it contains an unexpected character in line 1 and column 11.