2014-09-10 3 views
2

J'ai essayé d'implémenter la recherche dans mon gadget en utilisant LIKE requête.Requête de recherche PDO, faites comme les contacts android recherche

Maintenant, j'ai cette nouvelle exigence où je dois faire cette recherche comme la recherche Android ..

Requête:

$stmt = $conn->prepare("SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE LOWER(GUEST_FIRST_NAME) LIKE ? OR LOWER(GUEST_NAME) LIKE ?"); 
$stmt->execute(array('%'.strtolower($searchFilter).'%','%'.strtolower($searchFilter).'%')); 

Soit Supposons que j'ai une chaîne Syed Haider Hassan dans la base et si je recherche san dans la table de base de données en utilisant la requête donnée, il me trouvera cette chaîne ci-dessus. Par conséquent, si je mets tout ce qui correspond à l'intérieur ou ne importe où dans la chaîne, il me obtenir cette chaîne,

Mais ce que je veux est que lorsque je recherche dans la base de données Hai ou Has ou Sy il devrait me faire cette chaîne, mais si je recherche san ou même assan, la requête ne doit pas me montrer la chaîne. Signifie que si je recherche, il doit faire une recherche avec startwith, pas du milieu. Je pense qu'il pourrait être possible si je supprime % depuis le début, mais le problème est alors requête ne verra startwith sur Syed, je veux appliquer startwith sur chaque mot que les mots sont séparés par l'espace. Recherche SyedHaiderHassan différemment ..

Je sais ce que j'ai essayé d'expliquer ci-dessus est très déroutant, surtout parce que je ne suis pas bon en anglais. Mais en quelques mots si vous avez Android Mobile, j'ai Galaxy S4, rechercher un nom dans votre carnet d'adresses. Si vous cherchez à partir du milieu du mot, il ne cherchera pas, mais si vous cherchez à partir du début du mot, il cherchera, mais ce n'est pas le cas. Si le nom de votre contact est une combinaison de deux mots séparés par l'espace , il vérifie également le premier alphabet du deuxième mot.

J'espère que je suis clair, mais je ne sais pas comment implémenter cette requête. S'il vous plaît si quelqu'un peut mettre à jour ma requête à ce nouveau critère de recherche, je serai très heureux.

=======================================

MISE À JOUR

ok, j'ai essayé le match contre comme suggéré dans l'une des réponses en utilisant try catch, j'obtiens cette erreur. enter image description here

Voici le code que j'ai essayé.

$search_words = "+" . str_replace (" ", "* +", $searchFilter)."*"; 
     try { 
      $stmt = $conn->prepare("SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME, GUEST_NAME) against (:SEARCH in boolean mode)"); 
      $stmt->bindValue(':SEARCH', $search_words, PDO::PARAM_STR); 
      $stmt->execute(); 

     } 
     catch(PDOException $e){ 
      echo 'ERROR: ' . $e->getMessage(); 
     } 

Des idées pour résoudre ce problème?

===================================

Update 2

Ok, j'ai simplement mis les faits ici. Voici ma table Structure.

Si i Utiliser comme avec le caractère générique %%, il recherchera même à partir du milieu du nom.

Permet de voir le nom en surbrillance dans la capture d'écran, le nom en surbrillance est Lukasz Henryk. Si je recherche avec joker en utilisant comme% enry%, il me trouvera cette ligne. mais je ne veux pas ça, je veux que la recherche devrait mot avec le début du nom. e-g si je recherche Luk ou Hen ou He ou même H, il devrait me trouver cette rangée. Les moyens de départ de l'alphabet sont importants, si l'alphabet de départ ne correspond pas alors ne me donnez pas la ligne.

J'ai également essayé une requête comme wildcard comme ceci Henr% mais il ne fonctionne pas parce que cela ne fonctionne que pour Luk%, il considère toute colonne comme une seule chaîne.

Existe-t-il un moyen de dire à une requête de rechercher l'alphabet de départ après l'espace?

S'il vous plaît, quelqu'un Aidez-moi ici.

Répondre

0

Vous pouvez utiliser MySQL: s MATCH AGAINST. N'oubliez pas que vous devez créer un index FULLTEXT contenant GUEST_FIRST_NAME et GUEST_NAME (dans cet ordre).

Juste un exemple:

$string = "syed haider"; 
$search_words = "+" . str_replace (" ", "* +", $string)."*"; 

$query = "SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME) against ('$search_words' in boolean mode) OR MATCH (GUEST_NAME) against ('$search_words' in boolean mode)"; 

// SELECT ROOM, GUEST_NAME, GUEST_FIRST_NAME, CONFIRMATION_NO, DEPARTURE, PWD FROM RESERVATION_GENERAL_2 WHERE MATCH (GUEST_FIRST_NAME) against ('+syed* +haider*' in boolean mode) OR MATCH (GUEST_NAME) against ('+syed* +haider*' in boolean mode) 
+0

pouvez-vous s'il vous plaît faire ce travail de recherche dans pdo. Si possible, mettez à jour ma requête. Je ne suis pas bon avec les requêtes de base de données .. –

0

Avez-vous essayé mysql regexp (RLIKE)?

configuration de table

:

CREATE TABLE `user` (
    `name` varchar(50) NOT NULL DEFAULT '' 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

INSERT INTO `user` (`name`) 
VALUES 
    ('Syed Haider Hassan'); 

requête:

select * from user where name rlike '[[:<:]]Hass' 

retours:

name 
Syed Haider Hassan 

requête ne correspond pas à:

select * from user where name rlike '[[:<:]]san' 
:

retours

name 
+0

Rlike peut être très lent et gâcher les index. – unska

0

Votre problème provient de la chaîne de recherche ($ search_words = "+". str_replace ("", "* +", $ searchFilter). "*";), car l'opérateur relationnel est "+, -, <>, etc.", c'est pourquoi vous devez d'abord voir votre requête complète.

Faire ces étapes:

  1. écho votre requête SQL et essayez d'exécuter dans une interface graphique MySql (par exemple Navicat) pour être sûr que votre requête n'ont pas des erreurs.
  2. Assurez-vous que l'index des champs GUEST_FIRST_NAME, GUEST_NAME est "Texte intégral". Pour cela, vous devez exécuter "ALTER TABLE RESERVATION_GENERAL_2 AJOUTER FULLTEXT INDEX name_index (GUEST_FIRST_NAME, GUEST_NAME);"

Essayez ces étapes et faites le moi savoir.

1

Comme d'autres ont dit que l'index de texte intégral est la voie à suivre c'est ce que vous voulez que votre requête ressemble, le + fait tous les mots requis le laisser dehors pour rechercher n'importe quels mots.Vous ne pouvez pas utiliser le guillemet double ", avec le caractère générique *, ce qui est raisonnable car le guillemet double signifie exact mot. Ce qu'il ne peut pas être en utilisant le joker. (Ou du moins je n'ai pas encore trouver un moyen de le faire)

SELECT 
    ROOM, 
    GUEST_NAME, 
    GUEST_FIRST_NAME, 
    CONFIRMATION_NO, 
    DEPARTURE, 
    PWD 
FROM 
    RESERVATION_GENERAL_2 
WHERE 
    MATCH(GUEST_NAME, GUEST_FIRST_NAME) 
AGAINST 
    ('+word* +word2*' IN BOOLEAN MODE) 

Fondamentalement

$search_words = ''; 
foreach(explode(' ', $search) as $words){ 
     $search_words .= '+'.$word.'* '; 
} 

ET

... 
WHERE 
    MATCH(GUEST_NAME, GUEST_FIRST_NAME) 
AGAINST 
    (:search_words IN BOOLEAN MODE) 

$stmt->bindValue(':search_words', $search_words, PDO::PARAM_STR); 

Etc ...

Mais vous devez avoir un index de texte complet, dans ce cas un composite sur GUEST_NAME, GUEST_FIRST_NAME.

Voir aussi ce

MySQL Full Text Search Mystery

Questions connexes