<?php
namespace app\common\helper\tool\es;
/**
* es 条件生成
*/
use app\common\helper\tool\Arrays;
class Cd
{
/** @var string none */
const NONE = 'none';
/** @var string 等于 */
const EQ = 'eq';
/** @var string 包含 */
const IN = 'in';
/** @var string is not null */
const HAS = 'has';
/** @var string is null */
const EXC = 'exc';
/** @var string 大于 */
const GT = 'gt';
/** @var string 大于等于 */
const GTE = 'gte';
/** @var string 小于 */
const LT = 'lt';
/** @var string 小于等于 */
const LTE = 'lte';
const PRE_OP = [
self::GT,
self::GTE,
self::LT,
self::LTE,
self::EQ,
self::IN,
self::HAS,
self::EXC,
];
const SINGLE_OP = [
self::HAS,
self::EXC,
];
/** @var string and */
const AND = '&&';
/** @var string or */
const OR = '||';
/** @var string not */
const NOT = '!';
const PRE_TYPE = [
self:: AND => 'filter',
self:: OR => 'should',
self::NOT => 'must_not',
];
/** @var string 内部使用 */
const BOOL = 'bool';
/** @var string 元素 有这个key 说明该 元素是个bool 原始条件 */
const COND_KEY = 'BS_ES_COND_KEY_&&||!';
/** @var string 操作字段的键 */
const K = 'KEY';
/** @var string 条件值 */
const V = 'VALUE';
/**
* 得到查询条件
eg:
$a_arr = [
Cd:: AND => [
[Cd::K => 'id', Cd::V => [Cd::IN, [552646]]],
[
Cd::COND_KEY => [
Cd:: AND => [
[Cd::K => 'id', Cd::V => [Cd::GT, 552646]],
[Cd::K => 'id', Cd::V => [Cd::LT, 552646]]
],
]
]
],
];
$a_cond = Cd::getCondition($a_arr);
*
* @param array $a_param
* @return array ['bool' => [ 'filter' =>[], 'must_not' => [], 'should' => [] ]]
* @throws Exception
*/
public static function getCondition(array $a_param)
{
$a_param = self::checkSimple($a_param);
$a_cond = [];
foreach ($a_param as $s_k => $a_v) {
if (!key_exists($s_k, self::PRE_TYPE)) {
throw new Exception('condition type is not supported');
}
$a_cond[self::PRE_TYPE[$s_k]] = self::makeArrCond($a_v);
}
return [
self::BOOL => $a_cond
];
}
private static function makeArrCond(array $a_arr)
{
$a_tmp = [];
foreach ($a_arr as $m_v) {
if ($m_v[self::COND_KEY]) {
$a_tmp [] = self::getCondition($m_v[self::COND_KEY]);
} else {
$m_val = is_array($m_v[self::V]) ? $m_v[self::V] : [$m_v[self::V]];
$a_tmp [] = self::makeFieldCond($m_v[self::K], ...$m_val);
}
}
return $a_tmp;
}
private static function makeFieldCond($s_k, $s_op, $m_val = null)
{
if ($m_val === null) {
if (in_array($s_op, self::SINGLE_OP, true)) {
$m_val = $s_op;
} else {
$m_val = $s_op;
if (!is_array($m_val)) {
$s_op = self::EQ;
} else {
$s_op = self::NONE;
}
}
}
if (!in_array($s_op, self::PRE_OP) ||
!is_callable(__CLASS__ . '::' . $s_op) ||
$m_val === null
) {
throw new Exception('operation is not supported');
}
return self::$s_op($s_k, $m_val);
}
private static function checkSimple(array $a_param)
{
if (!self::hasPre($a_param)) {
if (key_exists(self::K, $a_param)) {
$a_param = [$a_param];
}
return [
self:: AND => $a_param
];
}
return $a_param;
}
private static function hasPre(array $a_param)
{
return count(array_intersect(array_keys(self::PRE_TYPE), array_keys($a_param))) > 0;
}
private static function in($s_k, $m_val)
{
if (!Arrays::isList($m_val)) {
throw new Exception('wrong value for operation - in');
}
return [
'terms' => [
$s_k => $m_val
]
];
}
private static function eq($s_k, $m_val)
{
return [
'term' => [
$s_k => $m_val
]
];
}
private static function gt($s_k, $m_val)
{
return self::range($s_k, $m_val, self::GT);
}
private static function gte($s_k, $m_val)
{
return self::range($s_k, $m_val, self::GTE);
}
private static function lt($s_k, $m_val)
{
return self::range($s_k, $m_val, self::LT);
}
private static function lte($s_k, $m_val)
{
return self::range($s_k, $m_val, self::LTE);
}
private static function range($s_k, $m_val, $s_op)
{
return [
'range' => [
$s_k => [
$s_op => $m_val
]
]
];
}
private static function has($s_k, $m_val)
{
return [
'exists' => [
'field' => $s_k
]
];
}
private static function exc($s_k, $m_val)
{
return [
"bool" => [
"must_not" => [
'exists' => [
'field' => $s_k
]
]
]
];
}
}
<?php
namespace app\common\helper\tool;
class Arrays
{
/**
* 验证数组是不是一个有值的标准list
*
* @param array $a_arr
* @return bool
*/
public static function isList(array $a_arr)
{
return array_keys($a_arr) === range(0, count($a_arr) - 1);
}
}