Recherche de texte intégral SQL Server
-
08-06-2019 - |
Question
Je travaille actuellement sur une application où nous avons une base de données SQL-Server et j'ai besoin de faire fonctionner une recherche en texte intégral qui nous permet de rechercher les noms des personnes.
Actuellement, l'utilisateur peut saisir un champ de nom qui recherche 3 colonnes varchar différentes.Prénom, nom, deuxième prénom
Disons donc que j'ai 3 lignes avec les informations suivantes.
1 - Phillip - J - Fry
2 - Amy - NULL - Wong
3 - Lion - NULL - Wong
Si l'utilisateur saisit un nom tel que « Fry », il renverra la ligne 1.Cependant, s'ils entrent dans Phillip Fry, Fr ou Phil, ils n'obtiennent rien.et je ne comprends pas pourquoi il fait ça.S'ils recherchent Wong, ils obtiennent les lignes 2 et 3. S'ils recherchent Amy Wong, ils n'obtiennent rien.
Actuellement, la requête utilise CONTAINSTABLE mais j'ai changé cela avec FREETEXTTABLE, CONTAINS et FREETEXT sans aucune différence notable dans les résultats.Les méthodes de table sont à privilégier car elles renvoient les mêmes résultats mais avec classement.
Voici la requête.
....
@Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE @SearchString varchar(100)
SET @SearchString = '"'+@Name+'"'
SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), @SearchString)
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;
....
Des idées...?Pourquoi cette recherche en texte intégral ne fonctionne pas correctement ?
La solution 3
Merci pour vos réponses les gars, j'ai enfin pu le faire fonctionner.Avec une partie des réponses de Biri et de Kibbee.J'avais besoin d'ajouter * à la chaîne et de la diviser en espaces pour fonctionner.Donc à la fin j'ai eu
....
@Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE @SearchString varchar(100)
--Added this line
SET @SearchString = REPLACE(@Name, ' ', '*" OR "*')
SET @SearchString = '"*'+@SearchString+'*"'
SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), @SearchString)
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;
....
Il y a plus de champs recherchés, je l'ai juste simplifié pour la question, désolé, je ne pensais pas que cela affecterait la réponse.Il recherche en fait une colonne contenant un csv de surnoms et une colonne de notes également.
Merci pour l'aide.
Autres conseils
FreeTextTable devrait fonctionner.
INNER JOIN FREETEXTTABLE(Person, (LastName, Firstname, MiddleName), @SearchString)
@SearchString doit contenir des valeurs telles que « Phillip Fry » (une longue chaîne contenant toutes les chaînes de recherche séparées par des espaces).
Si vous souhaitez rechercher Fr ou Phil, vous devez utiliser un astérisque :Phil* et Fr*
« Phil » recherche exactement le mot « Phil ».'Phil*' recherche tous les mots commençant par 'Phil'
Si vous recherchez uniquement les noms de personnes, il peut être dans votre intérêt de ne même pas utiliser l'index de texte intégral.L'index de texte intégral a du sens lorsque vous disposez de grands champs de texte, mais si vous traitez principalement un mot par champ, je ne suis pas sûr de la quantité supplémentaire que vous obtiendriez des index de texte intégral.Attendre que l'index de texte intégral se réindexe avant de pouvoir rechercher de nouveaux enregistrements peut être l'un des nombreux problèmes.
Vous pouvez simplement faire une requête telle que la suivante.Divisez votre chaîne de recherche en espaces et créez une liste des termes de recherche.
Select FirstName,MiddleName,LastName From person WHERE Firstname like @searchterm1 + '%' or MiddleName like @searchterm1 + '%' or LastName like @searchterm1 + '%' or Firstname like @searchterm2 + '%' etc....
Une autre approche pourrait consister à faire abstraction de la recherche des domaines individuels.
En d'autres termes, créez une vue sur vos données qui transforme tous les champs fractionnés comme le prénom et le nom en champs concaténés, c'est-à-direnom et prénom
Recherchez ensuite sur la vue.Cela simplifierait probablement la requête de recherche.
Vous voudrez peut-être vérifier Lucène.net comme alternative au texte intégral.