diff --git a/grammar/query.pp b/grammar/query.pp index a2474a9bd9..b55c8f9aba 100644 --- a/grammar/query.pp +++ b/grammar/query.pp @@ -29,6 +29,7 @@ %token database database %token collection collection %token sha256 sha256 +%token geolocation geolocation %token uuid uuid %token type type %token id id|recordid @@ -95,7 +96,8 @@ match_key: | key: - timestamp_key() + geolocation_key() + | timestamp_key() | ::meta_prefix:: meta_key() | ::field_prefix:: field_key() | field_key() @@ -104,6 +106,9 @@ key: | +#geolocation_key: + + #meta_key: word_or_keyword()+ @@ -174,6 +179,7 @@ keyword: | | | + | | | | diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/EqualExpression.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/EqualExpression.php index 06eb68cc24..a431bd12d1 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/EqualExpression.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/EqualExpression.php @@ -27,11 +27,16 @@ class EqualExpression extends Node throw new QueryException(sprintf('Value "%s" for key "%s" is not valid.', $this->value, $this->key)); } - $query = [ - 'term' => [ - $this->key->getIndexField($context, true) => $this->value - ] - ]; + if(method_exists($this->key, "buildQuery")) { + $query = $this->key->buildQuery($this->value, $context); + } + else { + $query = [ + 'term' => [ + $this->key->getIndexField($context, true) => $this->value + ] + ]; + } if ($this->key instanceof QueryPostProcessor) { return $this->key->postProcessQuery($query, $context); diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/GeolocationKey.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/GeolocationKey.php new file mode 100644 index 0000000000..9d8942e8f7 --- /dev/null +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/AST/KeyValue/GeolocationKey.php @@ -0,0 +1,75 @@ +matcher, trim($value), $matches) === 1) { + $lat = $matches[1]; + $lon = $matches[3]; + $dst = $matches[5]; + $uni = trim($matches[7]); + if(in_array($uni, $this->units)) { + return [ + 'geo_distance' => [ + 'distance' => $dst . $uni, + 'location' => [ + 'lat' => $lat, + 'lon' => $lon + ] + ] + ]; + } + } + return null; + } + + + private function __construct($type, $key) + { + $this->type = $type; + $this->key = $key; + } + + public function getIndexField(QueryContext $context, $raw = false) + { + return $this->key; + } + + public function isValueCompatible($value, QueryContext $context) + { + return preg_match($this->matcher, trim($value), $matches) === 1; + } + + public function __toString() + { + return $this->type; + } +} diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/NodeTypes.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/NodeTypes.php index 61e935208d..2ff7272030 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/NodeTypes.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/NodeTypes.php @@ -28,6 +28,7 @@ class NodeTypes const FLAG = '#flag'; const NATIVE_KEY = '#native_key'; const TIMESTAMP_KEY = '#timestamp_key'; + const GEOLOCATION_KEY = '#geolocation_key'; // Token types for leaf nodes const TOKEN_WORD = 'word'; const TOKEN_QUOTED_STRING = 'quoted'; diff --git a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/QueryVisitor.php b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/QueryVisitor.php index b94ab551a3..522666bcaa 100644 --- a/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/QueryVisitor.php +++ b/lib/Alchemy/Phrasea/SearchEngine/Elastic/Search/QueryVisitor.php @@ -108,6 +108,9 @@ class QueryVisitor implements Visit case NodeTypes::TIMESTAMP_KEY: return $this->visitTimestampKeyNode($element); + case NodeTypes::GEOLOCATION_KEY: + return $this->visitGeolocationKeyNode($element); + case NodeTypes::METADATA_KEY: return new AST\KeyValue\MetadataKey($this->visitString($element)); @@ -337,6 +340,11 @@ class QueryVisitor implements Visit }); } + private function visitGeolocationKeyNode(TreeNode $node) + { + return AST\KeyValue\GeolocationKey::geolocation(); + } + private function visitNativeKeyNode(TreeNode $node) { $this->assertChildrenCount($node, 1);