Changeset 82458 in spip-zone


Ignore:
Timestamp:
May 16, 2014, 3:35:08 PM (5 years ago)
Author:
rastapopoulos@…
Message:

Début d'API en tableau (donc générable depuis squelette) pour permettre de générer la requête SphinxQL.

Pour cela, lorsque la création d'un objet SphinxQLQuery, on peut passer un tableau optionnel qui va alors pré-remplir les morceaux de la requête. Bien sûr on peut toujours encore manipuler la requête après coup.

Pour l'instant ça doit normalement gérer tous les cas de champ mono-valué et multi-valué, avec toutes les comparaisons possibles, et avec l'option "not" aussi.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/indexer/trunk/lib/Sphinx/SphinxQLQuery.php

    r82439 r82458  
    8080    private $limit   = '';
    8181    private $facet   = [];
    82 
     82       
     83        public function __construct($query_description=array()) {
     84                if (!empty($query_description)){
     85                        // Index (mandatory)
     86                        if ($query_description['index']){
     87                                if (!is_array($query_description['index'])){
     88                                        $query_description['index'] = array($query_description['index']);
     89                                }
     90                                foreach ($query_description['index'] as $index){
     91                                        $this->from($index);
     92                                }
     93                        }
     94                       
     95                        // Fulltext search string (optional)
     96                        if (isset($query_description['fulltext']) and is_string($query_description['fulltext'])){
     97                                $this->where("match('".$query_description['fulltext']."')");
     98                        }
     99                       
     100                        // All filters
     101                        $as_count = 0;
     102                        if (isset($query_description['filters']) and is_array($query_description['filters'])){
     103                                foreach ($query_description['filters'] as $filter){
     104                                        // Mono value
     105                                        if (
     106                                                $filter['type'] == 'mono'
     107                                                and isset($filter['field']) and is_string($filter['field']) // mandatory
     108                                                and isset($filter['values']) // mandatory
     109                                        ){
     110                                                // Default comparision : =
     111                                                if (!isset($filter['comparison'])){
     112                                                        $filter['comparison'] = '=';
     113                                                }
     114                                               
     115                                                // Always work with an array of values
     116                                                if (!is_array($filter['values'])){
     117                                                        $filter['values'] = array($filter['values']);
     118                                                }
     119                                               
     120                                                // For each values, we build a comparision
     121                                                $comparisons = array();
     122                                                foreach ($filter['values'] as $value){
     123                                                        $comparisons[] = $filter['not'] ? '!':'' . '(' . $filter['field'] . $filter['comparison'] . $this->quote($value) . ')';
     124                                                }
     125                                                if ($comparisons){
     126                                                        $comparisons = join(' OR ', $comparisons);
     127                                                        $this->where($comparisons);
     128                                                }
     129                                        }
     130                                       
     131                                        // Multi value JSON
     132                                        if (
     133                                                $filter['type'] == 'multi_json'
     134                                                and isset($filter['field']) and is_string($filter['field']) // mandatory
     135                                                and isset($filter['values']) // mandatory
     136                                        ){
     137                                                // Always work with an array of values
     138                                                if (!is_array($filter['values'])){
     139                                                        $filter['values'] = array($filter['values']);
     140                                                }
     141                                               
     142                                                // For each values, we build an "in" select
     143                                                $where_ins = array();
     144                                                foreach ($filter['values'] as $value){
     145                                                        $this->select(
     146                                                                'IN(' . $filter['field'] . $this->quote($value) . ') as multi_json'.$as_count
     147                                                        );
     148                                                        $where_ins[] = 'multi_json'.$as_count . '=' . ($filter['not'] ? '0' : '1');
     149                                                }
     150                                                if ($where_ins){
     151                                                        $where_ins = join(' OR ', $where_ins);
     152                                                        $this->where($where_ins);
     153                                                }
     154                                        }
     155                                }
     156                        }
     157                }
     158               
     159                /**
     160                // exemple de description
     161                array(
     162                        'index' => 'visites',
     163                        'fulltext' => 'ma recherche',
     164                        'filters' => array(
     165                                array(
     166                                        'type' => 'mono',
     167                                        'field' => 'properties.lang',
     168                                        'values' => array('fr'),
     169                                        'comparison' => '!=', // default : =
     170                                ),
     171                                array(
     172                                        'type' => 'multi_json',
     173                                        'field' => 'properties.tags',
     174                                        'values' => array('pouet', 'glop'),
     175                                ),
     176                                array(
     177                                        'type' => 'distance',
     178                                        'center' => array(
     179                                                'lat' => 44.837862,
     180                                                'lon' => -0.580086,
     181                                        ),
     182                                        'fields' => array(
     183                                                'lat' => 'properties.geo.lat',
     184                                                'lon' => 'properties.geo.lon',
     185                                        ),
     186                                        'distance' => 10000,
     187                                        'comparison' => '>', // default : <=
     188                                ),
     189                                array(
     190                                        'type' => 'interval',
     191                                        'expression' => 'uint(properties.truc)',
     192                                        'intervals' => array(1,2,3,4,5),
     193                                        'field' => 'truc',
     194                                        'test' => 'truc = 2',
     195                                        'select' => 'interval(uint(properties.truc),1,2,3,4)',
     196                                        'where' => 'test = 2',
     197                                ),
     198                        ),
     199                        'orders' => array(
     200                                array(
     201                                        'field' => 'score',
     202                                        'direction' => 'asc', // default : desc
     203                                ),
     204                                array(
     205                                        'field' => 'distance',
     206                                        'center' => array(
     207                                                'lat' => 44.837862,
     208                                                'lon' => -0.580086,
     209                                        ),
     210                                        'fields' => array(
     211                                                'lat' => 'properties.geo.lat',
     212                                                'lon' => 'properties.geo.lon',
     213                                        ),
     214                                ),
     215                        ),
     216                        'facet' => array(
     217                                'field' => 'properties.tags',
     218                                'group_name' => 'tag',
     219                                'order' => 'tag asc', // default : count desc
     220                        ),
     221                );
     222                **/
     223        }
     224       
    83225    public function select($select) {
    84226        $this->select[] = $select;
     
    117259    }
    118260
    119     public function quote($recherche) {
    120         return _q($recherche);
    121     }
     261    function quote($value, $type='') {
     262                return
     263                        (is_numeric($value)) ? strval($value) :
     264                                (!is_array($value) ? ("'" . addslashes($value) . "'") :
     265                                        join(",", array_map(array($this, 'quote'), $value))
     266                                );
     267        }
    122268
    123269    public function get() {
     
    125271        if ($this->select)   $query[] = 'SELECT '   . implode(',', $this->select);
    126272        if ($this->from)     $query[] = 'FROM '     . implode(',', $this->from);
    127         if ($this->where)    $query[] = 'WHERE '    . implode(' AND ', $this->where);
     273        if ($this->where)    $query[] = 'WHERE ('   . implode(') AND (', $this->where) . ')';
    128274        if ($this->groupby)  $query[] = 'GROUP BY ' . implode(',', $this->groupby);
    129275        if ($this->orderby)  $query[] = 'ORDER BY ' . implode(',', $this->orderby);
Note: See TracChangeset for help on using the changeset viewer.