12
votes

SQL Server Recherche en texte intégral pour la correspondance exacte avec Fallback

Tout d'abord, il semble y avoir aucun moyen d'obtenir une correspondance exacte à l'aide d'une recherche en texte intégral. Cela semble être une question très discutée lors de l'utilisation de la méthode de recherche en texte intégral et de nombreuses solutions différentes pour atteindre le résultat souhaité, mais la plupart semblent très inefficaces. Être je suis obligé d'utiliser une recherche en texte intégral en raison du volume de ma base de données, j'ai récemment dû mettre en œuvre l'une de ces solutions pour obtenir des résultats plus précis.

Je ne pouvais pas utiliser le classement des résultats de la recherche de texte intégral car de savoir comment ça marche. Par exemple, si vous avez cherché un film appelé Toy Story CODE> et il y avait aussi un film appelé l'histoire derrière Toy Story code> qui viendrait au lieu de la correspondance exacte car elle a trouvé le mot histoire code> deux fois et jouet code>. p>

Je suivez mon propre classement que j'appelle "Popularité" chaque fois qu'un utilisateur accédait à un enregistrement le numéro monte. . J'utilise ce type de données pour pondérer mes résultats pour vous aider à déterminer ce que l'utilisateur pourrait rechercher. P>

J'ai aussi le problème où il faut parfois tomber à une recherche comme une recherche et ne pas renvoyer une correspondance exacte. C'est à dire. Recherche goonies code> devrait retourner les goonies code> (résultat le plus populaire) p>

Voici donc un exemple de ma procédure stockée actuelle pour la réalisation de ce: P>

DECLARE @Title varchar(255)
SET @Title = '"Toy Story"'
--need to remove quotes from parameter for LIKE search
DECLARE @Title2 varchar(255)
SET @Title2 = REPLACE(@title, '"', '')

--get top 100 results using full-text search and sort them by popularity
SELECT TOP(100) id, title, popularity As Weight into #TempTable FROM movies WHERE CONTAINS(title, @Title) ORDER BY [Weight] DESC

--check if exact match can be found
IF EXISTS(select * from #TempTable where Title = @title2)
--return exact match
SELECT TOP(1) * from #TempTable where Title = @title2
ELSE
--no exact match found, try using like with wildcards
SELECT TOP(1) * from #TempTable where Title like '%' + @title2 + '%'
DROP TABLE #TEMPTABLE


0 commentaires

4 Réponses :


2
votes

Cela vous donnera les films qui contiennent la phrase exacte "histoire de jouets", commandée par leur popularité.

SELECT
    m.[ID],
    m.[Popularity],
    k.[Rank]
FROM [dbo].[Movies] m
INNER JOIN CONTAINSTABLE([dbo].[Movies], [Title], N'"Toy Story"') as [k]
    ON m.[ID] = k.[Key]
ORDER BY m.[Popularity]


2 commentaires

Hey J Lo, cette méthode ne fonctionnera pas. J'ai besoin de quelque chose qui fera défaut à une correspondance exacte ou à utiliser le résultat le plus proche si non trouvé. L'utilisation de l'approche contentable a le même problème mentionné ci-dessus, par exemple si vous recherchez "Toy Story 2", il retournerait "histoire de jouets" comme résultat supérieur. Cela pourrait également être une limitation de texte intégral non d'indexation ou de caractères uniques correctement.


J'ai récemment désactivé toutes les mots d'arrêt / bruit afin que le classement complet du texte sera plus précis? Je vais retester cela et vous le faire savoir.



0
votes

Si vous avez le sentiment que vous n'aimez pas vraiment la partie floue de la recherche de texte complète, mais que vous faites comme la pièce de performance.

Peut-être est-ce qu'un chemin: si vous insistez pour obtenir la correspondance exacte avant une correspondance pondérée, vous pouvez essayer de hacher la valeur. Par exemple, 'Histoire de jouet' -> Apportez aux minuscules -> Histoire de jouet -> Hash dans 4DE2GS5SA (avec tout ce que vous aimez, vous aimez) et effectuez une recherche sur le hachage.


2 commentaires

Je dois utiliser une recherche de texte intégral pour saisir les 100 premiers résultats (il y a plus de 950 000 disques et 3-5K demandes une minute), je peux utiliser une méthode moins optimisée pour la recherche de ces 100. Convertir les titres aux hachons et effectuer un exact La recherche ne semble pas enlever aucune étape dans mon processus actuel?


Difficile de dire à partir de cette fin, vous avez besoin d'un top 100 - à côté des problèmes de performance - vous échappez-vous sans la recherche de texte complète? Si oui ... Le hachage peut être une bonne route. Les enregistrements 950K et 100 demandes par seconde doivent être possibles avec des index appropriés (et de plus en plus de demandes par seconde). Gardez l'index aussi petit que possible (pour la rendre en mémoire très facile) et testez le test de stress que la solution. Construisez un ensemble aléatoire de requêtes et mesurez le tout avant de choisir un chemin final.



0
votes

dans Oracle, j'ai utilisé UTL_Match à des fins similaires. ( http://docs.oracle.com/cd/e11882_01/ AppDev.112 / E25788 / U_MATCH.HTM )

Même si vous utilisez l'algorithme Jaro Winkler, par exemple, peut prendre un certain temps si vous comparez la colonne de titre du tableau 1 et de la table 2, vous pouvez améliorer les performances si vous rejoignez partiellement les 2 tables. Dans certains cas, j'ai comparé des noms de personnes sur le tableau 1 avec le tableau 2 à l'aide de Jaro Winkler, mais des résultats limités non seulement au-dessus d'un certain seuil de Winkler Jaro, mais également de noms entre les 2 tables où la première lettre est la même. Par exemple, je comparais Albert avec Aden, Alfonzo et Alberto, en utilisant Jaro Winkler, mais pas Albert et Frank (limitant le nombre de situations où l'algorithme doit être utilisé).

Jaro Winkler peut également convenir aux titres de film. Bien que vous utilisiez SQL Server (ne peut pas utiliser le package UTL_MATCH), il semble qu'il existe une bibliothèque gratuite appelée "Simmetrics" qui a l'algorithme Jaro Winkler parmi les autres métriques de comparaison de chaînes. Vous pouvez trouver des détails sur cela et les instructions ici: http: // anastasiosyal. com / post / 2009/01/11 / 18.aspx? #simmetrics


0 commentaires

5
votes

Vous devez utiliser une recherche en texte intégral contentable code> pour trouver les résultats du candidat Top 100 (éventuellement 200), puis commandez les résultats que vous avez trouvés à l'aide de vos propres critères.

On dirait que vous souhaitez que vous souhaitiez commander par code> p>

  1. correspondance exacte de la phrase ( = code>) li>
  2. la phrase entièrement assortie ( comme code>) li>
  3. valeur supérieure pour la popularité code> colonne li>
  4. le class code> dans le contient code> li> ol>

    mais vous pouvez jouir avec l'ordre exact que vous préférez. p>

    dans SQL qui ressemble à quelque chose comme: p>

    DECLARE @title varchar(255)
    SET @title = '"Toy Story"'
    --need to remove quotes from parameter for LIKE search
    DECLARE @title2 varchar(255)
    SET @title2 = REPLACE(@title, '"', '')
    
    SELECT
        m.ID,
        m.title,
        m.Popularity,
        k.Rank
    FROM Movies m
    INNER JOIN CONTAINSTABLE(Movies, title, @title, 100) as [k]
        ON m.ID = k.[Key]
    ORDER BY 
      CASE WHEN m.title = @title2 THEN 0 ELSE 1 END,
      CASE WHEN m.title LIKE @title2 THEN 0 ELSE 1 END,
      m.popularity desc,
      k.rank
    


5 commentaires

Pourriez-vous expliquer la commande par la section de cas, car d'une manière ou d'une autre, il fonctionne, mais il devrait lancer une "commande par numéro de position 0 est hors de portée du nombre d'éléments dans la liste Select" dans certains cas qui m'a très confus. Merci


@BFritz La commande par expressions ne se réfère pas à l'index du résultat. Mais les résultats sont énumérés dans l'ordre de la valeur de l'expression. Donc, pour la ligne où le titre est une correspondance exacte, la première expression ( quand m.title = @ title2 alors 0 autre 1 extrémité ) évalue à 0. Cette ligne est répertoriée avant toutes les autres lignes pour que le titre n'est pas une correspondance exacte. Pour pour ces lignes, la première expression évalue à 1.


Merci pour la réponse, je vais donner cela un coup de feu alors que j'essaie d'optimiser toutes mes procédures stockées lourdes (25 millions de demandes par jour), je dois voir si votre approche de jointure interne utilisera moins de ressources que ma sélection 100 dans une table #TEpp avec 2 sélectionneurs courir contre cela. Votre méthode est sûre de regarder plus agréable à lire.


@bfritz Vous pouvez également faire le même ordre sur la table Temp sur la table Temp, si la performance de la jointure est décevante. Faites-nous savoir ce qui fonctionne mieux!


Je viens d'ajouter cet ordre par trompe à l'approche Table Table: sqlfiddle.com/#!6/939C8 / 40 J'ai presque oublié pourquoi j'ai été forcé d'aller dans cette voie avec la table Temp et c'est due à la recherche exacte de la correspondance / comme Wildcard, qui ne peut pas être effectuée sur la table principale car elle dispose de plus de 2 millions d'enregistrements, mais Fonctionne parfaitement contre un top 100 des résultats de la recherche de texte intégral. Merci encore pour votre aide.