source: spip-zone/_plugins_/indexer/trunk/lib/Sphinx/SphinxQL/SphinxQL.php @ 105481

Last change on this file since 105481 was 105481, checked in by marcimat@…, 3 years ago

On réutilise la même connexion à Sphinx pour un même hit, en demandant un 'singleton'
de l’appel à SphinxQL. Ça retourne une unique instance de cette classe pour le host/port donné.

Sur la ?page=sphinx de démonstration, cela évite ~14 requêtes de connexion (grosso modo il y avait une connexion par requête à faire à Sphinx).
Et ça se ressent bien si on est en local et qu’on appelle un Sphinx distant.

A priori il ne devrait pas y avoir de bug avec ce changement.

File size: 4.3 KB
Line 
1<?php
2
3namespace Sphinx\SphinxQL;
4
5class SphinxQL {
6        private $host;
7        private $port;
8        private $sql; // objet MySQLi
9
10        public function __construct($host = '127.0.0.1', $port = 9306) {
11                $this->host = $host;
12                $this->port = $port;
13                $this->connect();
14        }
15
16        /**
17         * Se connecter à Sphinx
18        **/
19        public function connect() {
20                mysqli_report(MYSQLI_REPORT_STRICT);
21                try {
22                        $this->sql = new \MySQLi($this->host, null, null, null, $this->port);
23                } catch (\Exception $e) {
24                        spip_log('Connexion erronnée pour host : ' . $this->host . ' , port: ' . $this->port, 'indexer.' . _LOG_ERREUR);
25                        spip_log($e->getMessage(), 'indexer.' . _LOG_ERREUR);
26                        mysqli_report(MYSQLI_REPORT_OFF);
27                        return false;
28                }
29                mysqli_report(MYSQLI_REPORT_OFF);
30                return !!!$this->sql->connect_error;
31        }
32
33        /**
34         * Exécute une requête
35        **/
36        public function query($query) {
37                spip_log($query, 'indexer');
38
39                //Avant de laisser tomber, on retente un coup (se prémunir d'un timeout idiot suite à un long traitement)
40                if ($this->sql->connect_errno) {
41                    $this->sql->close();
42                    $this->connect();
43                }
44
45                if (!$this->sql) {
46                        return false;
47                }
48                return $this->sql->multi_query($query);
49        }
50
51
52        /**
53         * Échappe une chaîne
54        **/
55        public function escape_string($string) {
56                if (!$this->sql || $this->connect_errno) {
57                        return false;
58                }
59               
60                return $this->sql->escape_string($string);
61        }
62
63        /**
64         * Récupère les dernières erreurs
65        **/
66        public function errors() {
67                if (!$this->sql) {
68                        return false;
69                }
70               
71                return $this->sql->error_list;
72        }
73
74
75        /**
76         * Récupère toutes les informations de la requête ET ses metas
77        **/
78        public function allfetsel($query) {
79                if (!$this->sql) {
80                        return false;
81                }
82
83                $liste = array(
84                        'docs'   => array(),
85                        'facets' => array(),
86                        'meta'   => array(),
87                        'query'  => $query
88                );
89
90                try {
91                        $docs = $this->query($query);
92
93                        // les jeux de réponses sont les suivants :
94                        // 1) les documents trouvés
95                        // 2+) les FACET à la suite
96                        $reponses = array();
97                        do {
98                                if ($result = $this->sql->store_result()) {
99                                        $a = array(); while ($row = $result->fetch_assoc()) $a[] = $row;
100                                        $reponses[] = $a;
101                                        $result->free();
102                                }
103                        } while ($this->sql->more_results() AND $this->sql->next_result());
104
105                        $liste['docs']   = array_shift($reponses);
106                        $liste['facets'] = $this->parseFacets($reponses);
107                } catch  (\Exception $e) {
108                        echo "\n<div><tt>",htmlspecialchars($query),"</tt></div>\n";
109                        var_dump($e->getMessage());
110                        return false;
111                }
112
113                // recuperer les META
114                if ($meta = $this->sql->query('SHOW META')) {
115                        $a = array(); while ($row = $meta->fetch_assoc()) $a[] = $row;
116                        $liste['meta']   = $this->parseMeta($a);
117                }
118                else {
119                        $liste['meta']   = array('error' => 'meta illisible');
120                }
121
122                return array('query' => $liste);
123        }
124
125
126        /**
127         * Transforme un tableau de FACET en tableau PHP utilisable
128         *
129         * @param array $facettes
130         * @return array
131        **/
132        public function parseFacets($facettes) {
133                $facets = array();
134                if (is_array($facettes)) {
135                        foreach($facettes as $facette) {
136                                foreach ($facette as $i => $desc) {
137                                        $nb = $desc['count(*)'];
138                                        unset($desc['count(*)']);
139                                        $key  = array_keys($desc);
140                                        $key  = reset($key);
141                                        $value = array_shift($desc);
142                                        if (count($desc)) {
143                                                var_dump($desc);
144                                                die("Contenu non pris en compte dans FACET !");
145                                        }
146                                        if ($i == 0) {
147                                                $facets[$key] = array();
148                                        }
149                                        $facets[$key][$value] = $nb;
150                                }
151                        }
152                }
153               
154                return $facets;
155        }
156
157        /**
158         * Transforme un tableau des Metas en tableau PHP élaboré
159         *
160         * Regroupe entre autres les infos de keywords
161         */
162        public function parseMeta($metas) {
163                $liste = array();
164                foreach ($metas as $meta) {
165                        $cle = $meta['Variable_name'];
166                        $val = $meta['Value'];
167                        // cles keywords[0] ...
168                        if (substr($cle,-1,1) == ']') {
169                                list($cle, $index) = explode('[', $cle);
170                                $index = rtrim($index, ']');
171
172                                if (!isset($liste[$cle])) {
173                                        $liste[$cle] = array();
174                                }
175
176                                $liste[$cle][$index] = $val;
177                        } else {
178                                $liste[$cle] = $val;
179                        }
180                }
181               
182                if (isset($liste['keyword'])) {
183                        $liste['keywords'] = array();
184                        foreach ($liste['keyword'] as $index => $key) {
185                                $liste['keywords'][$key] = array(
186                                        'keyword' => $key,
187                                        'docs' => $liste['docs'][$index],
188                                        'hits' => $liste['hits'][$index],
189                                );
190                        }
191                        unset($liste['keyword'], $liste['docs'], $liste['hits']);
192                }
193               
194                return $liste;
195        }
196}
Note: See TracBrowser for help on using the repository browser.