mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
PHRAS-2009_Geo-operator_MASTER
add the "geolocation="lat lon distance" query
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
%token database database
|
%token database database
|
||||||
%token collection collection
|
%token collection collection
|
||||||
%token sha256 sha256
|
%token sha256 sha256
|
||||||
|
%token geolocation geolocation
|
||||||
%token uuid uuid
|
%token uuid uuid
|
||||||
%token type type
|
%token type type
|
||||||
%token id id|recordid
|
%token id id|recordid
|
||||||
@@ -95,7 +96,8 @@ match_key:
|
|||||||
| <id>
|
| <id>
|
||||||
|
|
||||||
key:
|
key:
|
||||||
timestamp_key()
|
geolocation_key()
|
||||||
|
| timestamp_key()
|
||||||
| ::meta_prefix:: meta_key()
|
| ::meta_prefix:: meta_key()
|
||||||
| ::field_prefix:: field_key()
|
| ::field_prefix:: field_key()
|
||||||
| field_key()
|
| field_key()
|
||||||
@@ -104,6 +106,9 @@ key:
|
|||||||
<created_on>
|
<created_on>
|
||||||
| <updated_on>
|
| <updated_on>
|
||||||
|
|
||||||
|
#geolocation_key:
|
||||||
|
<geolocation>
|
||||||
|
|
||||||
#meta_key:
|
#meta_key:
|
||||||
word_or_keyword()+
|
word_or_keyword()+
|
||||||
|
|
||||||
@@ -174,6 +179,7 @@ keyword:
|
|||||||
| <database>
|
| <database>
|
||||||
| <collection>
|
| <collection>
|
||||||
| <sha256>
|
| <sha256>
|
||||||
|
| <geolocation>
|
||||||
| <uuid>
|
| <uuid>
|
||||||
| <type>
|
| <type>
|
||||||
| <id>
|
| <id>
|
||||||
|
|||||||
@@ -27,11 +27,16 @@ class EqualExpression extends Node
|
|||||||
throw new QueryException(sprintf('Value "%s" for key "%s" is not valid.', $this->value, $this->key));
|
throw new QueryException(sprintf('Value "%s" for key "%s" is not valid.', $this->value, $this->key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = [
|
if(method_exists($this->key, "buildQuery")) {
|
||||||
'term' => [
|
$query = $this->key->buildQuery($this->value, $context);
|
||||||
$this->key->getIndexField($context, true) => $this->value
|
}
|
||||||
]
|
else {
|
||||||
];
|
$query = [
|
||||||
|
'term' => [
|
||||||
|
$this->key->getIndexField($context, true) => $this->value
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->key instanceof QueryPostProcessor) {
|
if ($this->key instanceof QueryPostProcessor) {
|
||||||
return $this->key->postProcessQuery($query, $context);
|
return $this->key->postProcessQuery($query, $context);
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
|
||||||
|
|
||||||
|
class GeolocationKey implements Key
|
||||||
|
{
|
||||||
|
const TYPE_GEOLOCATION = 'geolocation';
|
||||||
|
|
||||||
|
private $type;
|
||||||
|
private $key;
|
||||||
|
private $matcher = '/^(-?\\d*(\\.\\d*)?)[\\s]+(-?\\d*(\\.\\d*)?)[\\s]+(\\d*(\\.\\d*)?)(\\D*)$/';
|
||||||
|
private $units = [
|
||||||
|
'mi', 'miles',
|
||||||
|
'yd', 'yards',
|
||||||
|
'ft', 'feet',
|
||||||
|
'in', 'inch',
|
||||||
|
'km', 'kilometers',
|
||||||
|
'm', 'meters',
|
||||||
|
'cm', 'centimeters',
|
||||||
|
'mm', 'millimeters',
|
||||||
|
'NM', 'nmi', 'nauticalmiles',
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function geolocation()
|
||||||
|
{
|
||||||
|
return new self(self::TYPE_GEOLOCATION, 'geolocation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildQuery($value, QueryContext $context)
|
||||||
|
{
|
||||||
|
$matches = [];
|
||||||
|
if(preg_match($this->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ class NodeTypes
|
|||||||
const FLAG = '#flag';
|
const FLAG = '#flag';
|
||||||
const NATIVE_KEY = '#native_key';
|
const NATIVE_KEY = '#native_key';
|
||||||
const TIMESTAMP_KEY = '#timestamp_key';
|
const TIMESTAMP_KEY = '#timestamp_key';
|
||||||
|
const GEOLOCATION_KEY = '#geolocation_key';
|
||||||
// Token types for leaf nodes
|
// Token types for leaf nodes
|
||||||
const TOKEN_WORD = 'word';
|
const TOKEN_WORD = 'word';
|
||||||
const TOKEN_QUOTED_STRING = 'quoted';
|
const TOKEN_QUOTED_STRING = 'quoted';
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ class QueryVisitor implements Visit
|
|||||||
case NodeTypes::TIMESTAMP_KEY:
|
case NodeTypes::TIMESTAMP_KEY:
|
||||||
return $this->visitTimestampKeyNode($element);
|
return $this->visitTimestampKeyNode($element);
|
||||||
|
|
||||||
|
case NodeTypes::GEOLOCATION_KEY:
|
||||||
|
return $this->visitGeolocationKeyNode($element);
|
||||||
|
|
||||||
case NodeTypes::METADATA_KEY:
|
case NodeTypes::METADATA_KEY:
|
||||||
return new AST\KeyValue\MetadataKey($this->visitString($element));
|
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)
|
private function visitNativeKeyNode(TreeNode $node)
|
||||||
{
|
{
|
||||||
$this->assertChildrenCount($node, 1);
|
$this->assertChildrenCount($node, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user