Comment implémenter simplement une recherche temps réel pour votre site internet en conservant la maîtrise de vos données/statistiques ?
Plusieurs solutions existent et permettent d'intégrer une recherche temps réel sur un site internet.
Certaines sont payantes et vos données / statistiques sont sur leurs serveurs, par exemple Algolia.
D'autres sont gratuites, mais nécessitent un serveur physique dédié (qui lui n'est pas gratuit) et peuvent être complexes à mettre en place pour un prototype (ça prend du temps), par exemple ElasticSearch.
Comment faire si on souhaite intégrer rapidement la recherche temps réel sur un site internet tout en conservant la maîtrise des données/statistiques ?
Nous avons commencé à développer une solution : js-php-real-time-search.
Elle est utilisée sur notre Portail Web Lyonnais.
Un serveur http du type Apache, c'est un logiciel libre.
PHP doit être installé, php est un langage de programmation libre principalement utilisé dans le développement internet.
Composer est un gestionnaire libre de dépendances pour php, il permet de déclarer et d'installer automatiquement des librairies tierces.
php inclut par défaut la base de données sqlite.
sqlite a une extension fts4 qui permet d'effectuer des recherches plein texte.
sqlite est suffisant pour un site de petite et moyenne taille, surtout si on accède la plupart du temps à la base de données en lecture seule.
Activer l'option Keep-Alive dans votre fichier .htaccess.
Cette option permet de transmettre plusieurs requêtes via la même connexion TCP et peut diviser par deux les temps de latence.
<IfModule mod_headers.c>
Header set Connection Keep-Alive
</IfModule>
Exécuter dans un invité, la ligne de commande ci-dessous :
php -r "readfile('https://getcomposer.org/installer');" | php
Cela affiche :
#!/usr/bin/env php
All settings correct for using Composer
Downloading...
Composer successfully installed to: C:\tmp\composer.phar
Use it: php composer.phar
Un fichier composer.phar est maintenant présent dans le répertoire courant.
Créer un fichier composer.json dans le répertoire courant contenant :
{
"require": {
"glicer/search": "dev-master"
}
}
À partir du même répertoire que composer.json, exécuter dans un invité, la ligne de commande ci-dessous :
php composer.phar install
Cela affiche :
Loading composer repositories with package information
Installing dependencies (including require-dev)
- Installing symfony/stopwatch (v2.3.31)
Loading from cache
- Installing symfony/yaml (v2.3.31)
Loading from cache
- Installing symfony/filesystem (v2.3.31)
Loading from cache
- Installing symfony/finder (v2.3.31)
Loading from cache
- Installing symfony/console (v2.3.31)
Loading from cache
- Installing glicer/search (dev-master af5dee8)
Cloning af5dee89a0c30955bcef954283b670dae226151e
symfony/console suggests installing symfony/event-dispatcher ()
Writing lock file
Generating autoload files
Après installation, le répertoire courant contient les fichiers et répertoires ci-dessous :
composer.json
composer.phar
composer.lock
vendor
├───composer
├───glicer
│ └───search
│ ├───doc
│ ├───samples
│ ├───src
│ └───tests
└───symfony
Les données à indexer doivent être pour le moment au format yaml et encodées en utf8.
Un exemple ci-dessous :
cinema_comoedia:
title : "Cinéma Comoedia"
link: "http://www.cinema-comoedia.com"
sociallink: "https://www.facebook.com/cinemacomoedia"
feedlink: "http://www.cinema-comoedia.com/rss/"
feedlimit: 5
tags: "cinéma"
gps: "45.7473766,4.8355764"
description: |
Cinéma indépendant art et essai, lieu de rencontres dans lequel
projections de films, expositions, conférences et débats sont également possibles ...
address: "13 Avenue Berthelot"
city: "Lyon 7"
phone: "04 26 99 45 00"
jp_coureur_des_berges:
title : "Jean-Pierre, le coureur des berges du Rhône"
sociallink: "https://fr-fr.facebook.com/pages/Jean-Pierre-le-coureur-des-berges-du-Rh%C3%B4ne/101738059870725"
rel: ""
tags: "athlète papy joggeur short rouge"
description: |
Courir, courir, et encore courir... sans jamais s'arrêter ...
Exécuter le code php ci-dessous pour indexer les données dans la base de données sqlite.
Il faut notamment indiquer :
<?php
use Symfony\Component\Console\Output\ConsoleOutput;
use GlSearchEngine\GlServerEngine;
$output = new ConsoleOutput();
$yamlFiles = [__DIR__ . "/data/web.yml", __DIR__ . "/data/web2.yml"]; //liste des fichiers yaml à importer
$dbname = __DIR__ . "/data/web.db"; //chemin de la base sqlite où seront stockées les données
$table = "web"; //préfixe des tables créées
$fieldsFullText = ['title', 'tags', 'description', 'address', 'city']; //liste des champs yaml utilisés pour la recherche plein texte
$fieldsFilter = ['gps']; //liste des champs yaml éventuellement utilisés pour filtrer une recherche
$engine = new GlServerEngine($dbname, $output, true);
$engine->importYaml(
$table,
$fieldsFilter,
$fieldsFullText,
$yamlFiles,
function () use ($output) { //fonction appelée à chaque importation
$output->write(".");
}
);
Le client effectue un HTTP GET sur le serveur
Le serveur répond dans le format json.
Ci-dessous un exemple search.php :
<?php
include('php/vendor/glicer/search/src/GlServerSearch.php');
use GlSearchEngine\GlServerSearch;
$query = null;
$filter = null;
if (isset($_GET['q'])) {
$query = $_GET['q'];
}
if (!$query) {
return;
}
if (isset($_GET['f'])) {
$filter = $_GET['f'];
}
$dbname = __DIR__ . "/web.db";
$fields = ['title', 'tags', 'description', 'address', 'city']; //réindiquer la liste des champs destinés à la recherche full-text
$search = new GlServerSearch($dbname, "web", $fields);
$json = $search->queryJson($query, $filter);
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json;charset=utf-8;');
echo $json;
La partie client est réalisée en typescript : glsearch.ts
Intégrer glsearch.js dans votre fichier .html.
Utiliser la fonction query de glsearch pour interroger le serveur, ses paramètres sont :
La bibliothèque jquery et le fichier glsearch.js sont nécessaires.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery.min.js"></script>
<script src="js/glsearch.js"></script>
<style>
b {
color: blue;
}
</style>
</head>
<body>
<form>
<fieldset>
<label for="target">Search : </label>
<input id="target" type="text">
</fieldset>
</form>
<div id="result">
</div>
<script>
var view = function (fields) {
var html = "";
for (var field in fields) {
html += fields[field] + "<br>";
}
return html;
};
var client = new glSearch("http://lyon.glicer.com/search/search.php?q={q}&f={f}");
$("#target").keyup(function (event) { //événement déclenché à chaque frappe sur le clavier
var val = $(this).val();
var result = $('#result');
var html = "<div>";
client.query(val,
function (value) { //ajoute chaque élément pour construire le code html à intégrer
html += "<div>";
html += view(value);
html += "</div>";
html += "<br>";
},
function (values) {
if (values == null) {
result.empty(); //si aucun résultat, efface l'affichage
} else {
html += "</div>";
result.empty();
result.append(html); //affiche le résultat final
}
});
});
</script>
</body>
</html>
Auracom - 12/10/2015 11:52
Bonjour Pourriez vous faire un test avec 100.000 enregistrements ? Merci
dev_glicer - 12/10/2015 22:38
Nous n'avons pas à disposition une telle base, nous ne pensons pas que notre solution soit pour l'instant pertinente pour autant de données.
Nous l'avons utilisé pour notre prototype.