1

SQL 2008サーバーでcontainstableとcontainsおよびfreetextを使用して、検索結果をランク付けできることを読みました。最近、初めてフリーテキストを使用しました。フリーテキストは単語を個別にループし、インデックス付きの列と比較します。最初にフレーズを検索し、次に単一の単語を検索できるようにしたいと思います。

説明列にインデックスが付けられているとします。私は次のようなストアドプロシージャクエリを使用しています:

SELECT id, description, item from table where (FREETEXT(description,@strsearch))

たとえば、3つの行セットにリンゴが含まれる単語が含まれていて、「アップルケーキ」を検索した場合、id2の行セットが最初になり、次に他の2つが続くはずです。

id1 apple pie 4/01/2012
id2 apple cake 2/29/2011
id3 candy apple 5/9/2011

たとえば、4つの行セットに食べ物が含まれる単語が含まれていて、「ファーストフードレストラン」を検索した場合、id3の行セットが最初になり、次にid1が続きます(完全に一致するわけではありませんが、列に「ファーストフード」があるため) 、その後、他の2つは次のようになります。

id1 McDonalds fast food
id2 healthy food
id3 fast food restaurant
id4 Italian restaurant
4

1 に答える 1

1

この記事は役に立ちますか?

MSDN:ランク付けされた結果セットの制限(全文検索)

これは、追加のパラメーターを使用すると、結果を最も関連性の高いもの(を使用して影響を与えることができる)に制限し、WEIGHTその関連性()で並べ替えることができることを意味しますRANK

top_n_by_rankは整数値nであり、上位n個の一致のみが降順で返されることを指定します。

FREETEXTドキュメントには;の例がありません。参照するだけですCONTAINSTABLE。しかし、それは間違いなく、に使用できる列をCONTAINSTABLE出力することを意味します。RANKORDER BY

関連性の独自の定義を強制する方法があるかどうかはわかりません。FTSに従って上位10の関連する一致を引き出し、出力に独自のランキングを適用することは理にかなっています。たとえば、関数を使用して検索語を分割し、一致した単語の数で並べ替えることができます。次の例の単純さと簡単な再現のために、サブクエリでフルテキストを使用していませんが、実際に実行しているものに置き換えることができます。まず、関数を作成します。

IF OBJECT_ID('dbo.SplitStrings') IS NOT NULL
  DROP FUNCTION dbo.SplitStrings;
GO
CREATE FUNCTION dbo.SplitStrings(@List NVARCHAR(MAX))
RETURNS TABLE
AS
   RETURN ( SELECT Item FROM
       ( SELECT Item = x.i.value('(./text())[1]', 'nvarchar(max)')
         FROM ( SELECT [XML] = CONVERT(XML, '<i>'
         + REPLACE(@List, ' ', '</i><i>') + '</i>').query('.')
           ) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
       WHERE Item IS NOT NULL
   );
GO

次に、マッチングを実行する方法を示す簡単なスクリプト:

DECLARE @foo TABLE
(
    id INT,
    [description] NVARCHAR(450)
);

INSERT @foo VALUES
(1,N'McDonalds fast food'),
(2,N'healthy food'),
(3,N'fast food restaurant'),
(4,N'Italian restaurant'),
(5,N'Spike''s Junkyard Dogs');

DECLARE @searchstring NVARCHAR(255) = N'fast food restaurant';

SELECT x.id, x.[description]--, MatchCount = COUNT(s.Item)
FROM
(
    SELECT f.id, f.[description]
    FROM @foo AS f

    -- pretend this actually does full-text search:
    --where (FREETEXT(description,@strsearch))

    -- and ignore how I actually matched:    
    INNER JOIN dbo.SplitStrings(@searchstring) AS s
    ON CHARINDEX(s.Item, f.[description]) > 0

    GROUP BY f.id, f.[description] 
) AS x
INNER JOIN dbo.SplitStrings(@searchstring) AS s
ON CHARINDEX(s.Item, x.[description]) > 0
GROUP BY x.id, x.[description]
ORDER BY COUNT(s.Item) DESC, [description];

結果:

id description
-- -----------
3  fast food restaurant
1  McDonalds fast food
2  healthy food
4  Italian restaurant
于 2012-04-28T21:02:50.843 に答える