IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MySQL Discussion :

Implémentation d'un moteur de recherche interne


Sujet :

MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Par défaut Implémentation d'un moteur de recherche interne
    Bonjour,

    Je travaille sur un site web et j'aimerais améliorer mon moteur de recherche. Je n'attends pas spécialement de code, mais ce que je veux c'est surtout savoir si ce que je veux faire est faisable et où orienter mes recherches. Bien entendu, je ne dirais pas non à des exemples de code SQL.
    Alors j'ai une page "recherche avancée" sur le site qui permet de trouver des utilisateurs selon plusieurs critères. Par exemple, on peut trouver des utilisateurs vivant dans un pays en particulier, professionnels dans un domaine spécifique, etc. Je voudrais ordonner les résultats de manière à avoir les utilisateurs qui remplissent tous les critères, puis ceux qui en remplissent deux sur trois, puis ceux qui en remplissent un sur trois. Je précise que dans ma requête je fais des "OU" (OR) entre les critères. Y a-t-il un moyen d'y arriver depuis MySQL ou faut-il traiter les résultats après dans mon code ?
    L'autre chose c'est le stockage des résultats. Disons que j'ai une requête plus complexe, sur plusieurs tables. Je cherche un moyen de stocker les résultats, ou en tout cas d'éviter au serveur d'avoir à refaire tout le travail à chaque fois que l'utilisateur veut passer à la page suivante/précédente. Quelle est la meilleure approche? Idéalement je souhaiterais avoir une solution qui n'est pas trop chronophage.
    La dernière chose, et là c'est vraiment un bonus, c'est obtenir des résultats en cas de mauvaise orthographe d'un critère. Si un utilisateur recherche des membres s'appelant "Anna", pouvoir lui proposer des "Ana". J'ai réussi à le faire avec les villes en ayant une base de données d'orthographes différentes, est-ce qu'il y a un moyen de le faire ici?

    Merci

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 010
    Billets dans le blog
    6
    Par défaut
    REMARQUE GÉNÉRALE : votre question aurait été plus adéquate dans le forum SGBD en général...

    Citation Envoyé par dré kam Voir le message
    Alors j'ai une page "recherche avancée" sur le site qui permet de trouver des utilisateurs selon plusieurs critères. Par exemple, on peut trouver des utilisateurs vivant dans un pays en particulier, professionnels dans un domaine spécifique, etc. Je voudrais ordonner les résultats de manière à avoir les utilisateurs qui remplissent tous les critères, puis ceux qui en remplissent deux sur trois, puis ceux qui en remplissent un sur trois. Je précise que dans ma requête je fais des "OU" (OR) entre les critères. Y a-t-il un moyen d'y arriver depuis MySQL ou faut-il traiter les résultats après dans mon code ?
    Il n'y a pas d'automatisme possible à ce niveau. Vous pouvez éventuellement faire une procédure stockée avec du SQL dynamique qui est généré en dégradant les critères associés à un score (exemple : SELECT 1 AS SCORE, * FROM ... WHERE <tous les critères> UNION ALL SELECT 2 AS SCORE, * FROM ... WHERE <tous les critères - 1> UNION ALL SELECT 3 AS SCORE, * FROM ... WHERE <tous les critères -2> ), mais c'est complexe à réaliser et fastidieux...
    Une autre solution est de tout faire via la recherche FULL TEXT. Hélas le moteur Full Text de MySQL est une vraie merde.
    Dans d'autres SGBDR (MS SQL Server pour ne pas le citer) vous pouvez obtenir une réponse avec un "score" de recherche. Le prédicat devient :
    FREETEXTTABLE(<liste_colonnes_de_recherche>, 'tous les mots clef')
    Lisez le papier que j'ai écrit à ce sujet : https://blog.developpez.com/sqlpro/p...text_search_no

    L'autre chose c'est le stockage des résultats. Disons que j'ai une requête plus complexe, sur plusieurs tables. Je cherche un moyen de stocker les résultats, ou en tout cas d'éviter au serveur d'avoir à refaire tout le travail à chaque fois que l'utilisateur veut passer à la page suivante/précédente. Quelle est la meilleure approche? Idéalement je souhaiterais avoir une solution qui n'est pas trop chronophage.
    Il suffit de stocker les clefs du résultat dans une table temporaire locale ou globale ou encore une pseudo table temporaire (qui a ma préférence) avec en sus une colonne d'ordonnancement. Puis de réutiliser cette table temporaire pour chaque accès page. Pour mieux faire, il faut taguer les données de cette table avec un identifiant de session. Là aussi MySQL n'est pas à l'aide vue la pauvreté de son niveau de SQL, car il faudrait implémenter les fonction de fenêtrage et d'ordonnancement comme RANK, ROW_NUMBER, etc.
    A lire sur le sujet : http://sqlpro.developpez.com/article...clause-window/
    Là encore, je ne saurait trop vous recommander l'usage de SQL Server qui est le SGBDR le plus complet et le plus normatif à ce jour.
    La dernière chose, et là c'est vraiment un bonus, c'est obtenir des résultats en cas de mauvaise orthographe d'un critère. Si un utilisateur recherche des membres s'appelant "Anna", pouvoir lui proposer des "Ana". J'ai réussi à le faire avec les villes en ayant une base de données d'orthographes différentes, est-ce qu'il y a un moyen de le faire ici?
    Il existe des solutions pour faire de la correction automatique de saisie, tel que l'algorithme du dictionnaire de KNUTH, ou encore en passant par des fonctions de rapprochement tel que le LEVENSHTEIN, le HAMMING ou l'inférence directe dont je suis l'auteur et qui est actuellement utilisée par la Police pour la traque des terroristes...
    Mais encore faudrait-il avoir accès à la liste des mots indexés afin de préparer les codes correcteurs (par exemple pour l'algo du dico de KNUTH) afin d'être efficace. Malheureusement je ne pense pas qu'il soit possible de le faire avec MySQL...
    Là encore, MS SQL Server aurait été d'un grand secours, car on a toujours accès à toutes les tables internes afin d'étendre les capacités du moteur de recherche, ce que j'ai fait pour plusieurs de mes clients...
    Au sujet de la recherche de motif (nécessaire pour la comparaisons des dysorthographie) Lisez l'article que j'ai écrit à ce sujet : http://sqlpro.developpez.com/cours/s...aisons-motifs/

    Bref, orientez vous pour sur un vrai SGBDR et non pour un ersatz !!!
    https://blog.developpez.com/sqlpro/p...oudre_aux_yeux

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 955
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 955
    Par défaut
    Je voudrais ordonner les résultats de manière à avoir les utilisateurs qui remplissent tous les critères, puis ceux qui en remplissent deux sur trois, puis ceux qui en remplissent un sur trois. Je précise que dans ma requête je fais des "OU" (OR) entre les critères.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    case when colonne1 = '$critere1' then 1 else 0 end +
    case when colonne2 = '$critere2' then 1 else 0 end +
    case when colonne3 = '$critere3' then 1 else 0 end as nb_critere
    devrait permettre de trié sur le nb_critere desc pour avoir ceux qui en remplissent le plus en 1er.
    Ce CASE sera à générer dynamiquement en fonction des critères sélectionnés.

    Disons que j'ai une requête plus complexe, sur plusieurs tables. Je cherche un moyen de stocker les résultats, ou en tout cas d'éviter au serveur d'avoir à refaire tout le travail à chaque fois que l'utilisateur veut passer à la page suivante/précédente.
    Plutôt que de stocker le résultat de la requête, ce qui peut être coûteux si la requête renvoie un très grand nombre de ligne (nécessite de stocker l'intégralité du résultat même si l'utilisateur ne consulte que 10 lignes), vous pourriez stocker le résultat du select complexe avec jointure.
    Sur oracle, j'utiliserai une vue matérialisée rafraichie périodiquement avec des index bitmap sur les colonnes de filtre utilisée dans les conditions OR.
    Mais mysql ne propose ni vue matérialisée ni index bitmap, cependant vous pouvez toujours avoir une table qui stocke le résultat de la requête et un cron qui rafraichie périodiquement cette table, et utiliser des index classique.
    Le SELECT de recherche avec les critères dynamiques s'appuiera sur cette table.

    Après tout dépend de la volumétrie de base, le SELECT complexe peut être très efficace sans avoir besoin de stocker son résultat.

  4. #4
    Membre très actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    case when colonne1 = '$critere1' then 1 else 0 end +
    case when colonne2 = '$critere2' then 1 else 0 end +
    case when colonne3 = '$critere3' then 1 else 0 end as nb_critere
    devrait permettre de trié sur le nb_critere desc pour avoir ceux qui en remplissent le plus en 1er.
    Ce CASE sera à générer dynamiquement en fonction des critères sélectionnés.


    Plutôt que de stocker le résultat de la requête, ce qui peut être coûteux si la requête renvoie un très grand nombre de ligne (nécessite de stocker l'intégralité du résultat même si l'utilisateur ne consulte que 10 lignes), vous pourriez stocker le résultat du select complexe avec jointure.
    Sur oracle, j'utiliserai une vue matérialisée rafraichie périodiquement avec des index bitmap sur les colonnes de filtre utilisée dans les conditions OR.
    Mais mysql ne propose ni vue matérialisée ni index bitmap, cependant vous pouvez toujours avoir une table qui stocke le résultat de la requête et un cron qui rafraichie périodiquement cette table, et utiliser des index classique.
    Le SELECT de recherche avec les critères dynamiques s'appuiera sur cette table.

    Après tout dépend de la volumétrie de base, le SELECT complexe peut être très efficace sans avoir besoin de stocker son résultat.
    Je ne vous suis pas. Quelle est la différence entre stocker un SELECT et stocker le résultat?

  5. #5
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 955
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 955
    Par défaut
    Citation Envoyé par dré kam Voir le message
    Je ne vous suis pas. Quelle est la différence entre stocker un SELECT et stocker le résultat?
    Stocker le résultat du SELECT sans les critères de recherche afin d'avoir une table dédiée à la recherche à requêter avec les critères des utilisateurs versus stocker le résultat de chaque recherche effectuée par les utilisateurs comme vous sembliez le proposer.

  6. #6
    Membre très actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Par défaut
    Merci @SQLPro pour votre réponse complète. Alors j'ignorais l'existence des tables temporaires. Je viens de lire la documentation ( https://dev.mysql.com/doc/refman/5.7...ary-table.html ) et j'ai quelques questions à ce sujet. Il est indiqué que la table est supprimée à la fin de la session MySQL. Dans le cas d'un site web, la connexion avec la BDD est souvent fermée et ouverte, ça ne veut pas dire que la table serait supprimée dès l'affichage de la première page de résultats? Je pense à utiliser un table classique et à stocker les résultats de recherche ainsi que l'identifiant de la sélection PHP en cours, puis supprimer les lignes liées quand l'utilisateur se déconnecte. Je pourrais aussi faire une procédure qui supprime les entrées datant de plus d"une semaine par exemple.

    Est-ce que je devrais créer une autre discussion dans le forum SGBD?

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 010
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par dré kam Voir le message
    Merci @SQLPro pour votre réponse complète. Alors j'ignorais l'existence des tables temporaires. Je viens de lire la documentation ( https://dev.mysql.com/doc/refman/5.7...ary-table.html ) et j'ai quelques questions à ce sujet. Il est indiqué que la table est supprimée à la fin de la session MySQL. Dans le cas d'un site web, la connexion avec la BDD est souvent fermée et ouverte, ça ne veut pas dire que la table serait supprimée dès l'affichage de la première page de résultats? Je pense à utiliser un table classique et à stocker les résultats de recherche ainsi que l'identifiant de la sélection PHP en cours, puis supprimer les lignes liées quand l'utilisateur se déconnecte. Je pourrais aussi faire une procédure qui supprime les entrées datant de plus d"une semaine par exemple.

    Est-ce que je devrais créer une autre discussion dans le forum SGBD?
    Effectivement c'est pourquoi je proposait une table pseudo temporaire, c'est à dire une table en dur dans votre application qui contient différentes colonnes tel que :
    • un identifiant de session (par exemple un GUID)
    • une dateHeure de la session
    • un INT pour les clefs à stocker (par exemple n° d'article si c'est un site de vente)
    • une INT avec l'ordre de 1 à N


    Et il suffit de conserver dans votre session PHP ou dans un cookie du navigateur la valeur du GUID de session de l'internaute, voire même le passer directement dans les paramètres des pages HTML.

    Et vider non pas toutes les semaine, mais toutes les 12 heures au maximum (sur de gros sites web marchand je met 30 minutes, avec rafraichissement)... Les internautes mangent ! et une session authentifié à une limite der durée !!!

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  8. #8
    Membre très actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Effectivement c'est pourquoi je proposait une table pseudo temporaire, c'est à dire une table en dur dans votre application qui contient différentes colonnes tel que :
    • un identifiant de session (par exemple un GUID)
    • une dateHeure de la session
    • un INT pour les clefs à stocker (par exemple n° d'article si c'est un site de vente)
    • une INT avec l'ordre de 1 à N


    Et il suffit de conserver dans votre session PHP ou dans un cookie du navigateur la valeur du GUID de session de l'internaute, voire même le passer directement dans les paramètres des pages HTML.

    Et vider non pas toutes les semaine, mais toutes les 12 heures au maximum (sur de gros sites web marchand je met 30 minutes, avec rafraichissement)... Les internautes mangent ! et une session authentifié à une limite der durée !!!

    A +
    Oui, je pense que cette approche résout parfaitement le problème. Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Moteur de recherche interne sans pubs
    Par oc_alex86 dans le forum Services
    Réponses: 5
    Dernier message: 29/01/2008, 04h10
  2. Moteur de recherche interne
    Par wasim dans le forum Services
    Réponses: 2
    Dernier message: 23/09/2007, 01h02
  3. [Tableaux] Moteur de recherche interne
    Par mchev dans le forum Langage
    Réponses: 3
    Dernier message: 01/02/2007, 01h20
  4. Moteur de recherche interne avec zope/python
    Par tunix dans le forum Zope
    Réponses: 3
    Dernier message: 01/05/2006, 15h45
  5. Un moteur de recherche interne
    Par kibodio dans le forum Langage SQL
    Réponses: 2
    Dernier message: 08/02/2005, 18h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo