2013-04-21 79 views
10

まず、フルテキスト検索を使用して完全一致を取得する方法がないようです。これは、フルテキスト検索方法を使用するときに非常に議論されている問題のようで、目的の結果を達成するためのさまざまなソリューションがありますが、ほとんどが非常に非効率的です。私は最近、データベースのボリュームのためにフルテキスト検索を使用する必要があります。私は最近、より正確な結果を得るためにこれらのソリューションの1つを実装しなければなりませんでした。SQL Serverのフルテキスト検索で、完全一致とフォールバックの一致

どのように動作するので、全文検索のランキング結果を使用できませんでした。たとえば、Toy Storyという映画を検索した場合、「Story」と「Toy」という単語が見つかったため、完全一致ではなくThe Story Behind Toy Storyという映画がありました。

ユーザーがレコードにアクセスする度に「人気度」と呼ばれる自分のランキングを追跡します。私はこのデータポイントを使用して、ユーザが何を探しているのかを判断するのに役立ちます。

また、LIKE検索にフォールバックして完全一致を返さない場合があるという問題もあります。私。 Gooniesを検索するとThe Goonies(最も人気のある結果は)

ので、ここではこれを達成するための私の現在のストアドプロシージャの例である返す必要があります:約5,000回分

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 

このストアドプロシージャが実行され、かつ十分なそれはだクレイジー私のサーバーを膝に持ってこないでください。しかし、これにもっと効率的なアプローチがあるかどうか本当に知りたいですか?ありがとう。

答えて

3

全文検索CONTAINSTABLEを使用して上位100件(おそらく200件)の候補結果を見つけ、独自の基準を使用して見つかった結果を注文する必要があります。

フレーズ(=

  • 完全に一致したフレーズ(LIKE
  • Popularity
  • の方が高い値と完全に一致ORDER BY

    1. したいようですねRankからCONTAINSTABLE

    しかし、あなたが好きな正確な順序で周りをおもしろくすることができます。

    のようなものになりますSQLでは:

    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 
    

    SQLFiddle

  • +0

    ORDER BY CASEセクションは何とか動作しているので説明できますか?「ORDER BYの位置番号0が選択リストの項目数の範囲外です」というケースがありますが、私は非常に混乱しています。ありがとう – bfritz

    +1

    @bfritz ORDER BY式は結果のインデックスを参照しません。しかし、結果は、式の値の順にリストされます。したがって、タイトルが完全一致である行の場合、最初の式( 'CASE WHEN m.title = @ title2 THEN 0 ELSE 1 END')は0と評価されます。この行は、タイトルが他のすべての行の前にリストされます完全一致これらの行については、最初の式は1と評価されます。 – flup

    +0

    レスポンスのおかげで、重いストアドプロシージャ(1日に2,500万回以上のリクエスト)を最適化しようとしているので、あなたの内部結合アプローチが、2つの選択肢を持つ#tempテーブルへの選択100より少ないリソースを使用する場合、それに対して実行されます。あなたの方法は確かに読めるように見えます。 – bfritz

    2

    これは、人気の順に並べられた、正確なフレーズ "トイストーリー"を含む映画を提供します。

    「The Goonies」を検索すると、上記の「Goonies Return」も表示されます。

    +0

    ねえJ Loのを参照してください、そのメソッドは動作しません。完全に一致するものをデフォルトにするか、見つからなければ最も近い結果を使用するものが必要です。 CONTAINSTABLEアプローチを使用すると、上記の同じ問題があります。たとえば、「Toy Story 2」を検索すると、「Toy Story」が結果として返されます。これは、フルテキストのインデックス番号や単一文字を正しく表示できないという制限もあります。 – bfritz

    +0

    私は最近、すべてのストップリスト/ノイズワードを無効にしたので、フルテキストランキングがより正確になるでしょうか?私はこれを再テストし、あなたに知らせるでしょう。 – bfritz

    0

    フルテキスト検索の曖昧な部分は本当に気に入らない気がしますが、あなたはパフォーマンスの部分が好きです。

    多分これはパスです:もしあなたが重み付けされたマッチの前に完全一致を得ることを主張するならば、値をハッシュしようとすることができます。たとえば、 'トイストーリー' - >小文字 - >トイストーリー - >ハッシュを4de2gs5saにハッシュして、ハッシュを検索します。

    +0

    私はトップ100の結果を取得するためにフルテキスト検索を使用する必要があります(そこには950kレコードと3から5k要求があります)。それらを検索するためにあまり最適化されていない方法を使用できます。タイトルをHashBytesに変換し、正確な検索は、私の現在のプロセスでは何の手続きも取っていないようです。 – bfritz

    +1

    このように言えば、パフォーマンスの問題の横にあるトップ100の結果が必要です。もしそうなら...ハッシングは良い道になるかもしれない。適切なインデックス(1秒あたりの要求数がさらに多い)で950Kレコードと100要求/秒が可能でなければなりません。インデックスを可能な限り小さくして(メモリに非常に簡単にフィットさせるため)、そのストレスをそのソリューションでテストします。クエリのランダムなセットを構築し、最終パスを選択する前にすべてを測定します。 – Paul

    0

    Oracleでは、同様の目的でUTL_MATCHを使用しました。 (http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_match.htm

    たとえば、Jaro Winklerアルゴリズムを使用しても、テーブル1とテーブル2のタイトル列を比較すると、2つのテーブルを部分的に結合するとパフォーマンスが向上することがあります。いくつかのケースでは、Jaro Winklerを使用してテーブル1のテーブル名とテーブル2のテーブル名を比較しましたが、特定のJaro Winklerしきい値を上回るだけでなく、最初の文字が同じ2テーブル間の名前も制限されていました。たとえばAlbertとAden、Alfonzo、AlbertoをJaro Winklerを使って比較しますが、AlbertとFrankはアルゴリズムを使用する必要のある状況の数を制限しません。

    Jaro Winklerは実際に映画のタイトルにも適しています。 SQLサーバーを使用していても(utl_matchパッケージは使用できません)、他の文字列比較メトリックの中でJaro Winklerアルゴリズムを持つ "SimMetrics"というフリーライブラリがあるようです。http://anastasiosyal.com/POST/2009/01/11/18.ASPX?#simmetrics

    関連する問題