3

非常に典型的なシナリオでは、Web アプリケーションに「検索」テキスト ボックスがあり、ユーザー入力がストアド プロシージャに直接渡されます。このストアド プロシージャは、フルテキスト インデックスを使用して、適切なキーを使用して結合された 2 つのテーブルの 2 つのフィールドを検索します。

CONTAINS 述語を使用してフィールドを検索しています。検索文字列を渡す前に、次のことを行います。

SET @ftQuery = '"' + REPLACE(@query,' ', '*" OR "') + '*"'

たとえば、城"the*" OR "castle*"に変更します。これが必要なのは、人々がcasで検索して、 Castleの結果を得られるようにしたいからです。

WHERE CONTAINS(Building.Name, @ftQuery) OR CONTAINS(Road.Name, @ftQuery)

問題は、各単語の末尾にワイルドカードを追加したため、ノイズ ワード (たとえば ) にもワイルドカードが追加されたため、削除されたように見えなくなったことです。これは、城を検索すると、劇場などの単語を含むアイテムが返されることを意味します。

OR を AND に変更することを最初に考えましたが、クエリでノイズ ワードが使用された場合、単純に一致が返されないように見えます。

私が達成しようとしているのは、ユーザーが検索している単語の全体または接頭辞を表すスペースで区切られた複数の単語を任意の順序で入力できるようにすることです。彼らが城を検索すると、アイテムの大きなリストが得られ、リストの真ん中に必要な結果が得られます.

先に進んで独自のノイズ ワード除去手順を実装することもできますが、それは全文索引作成で処理できるように思われます。

助けてくれてありがとう!

ジェイミー

4

5 に答える 5

2

私は同じ質問をしましたが、徹底的な検索の結果、良い解決策がないという結論に達しました.

妥協案として、ブルート フォース ソリューションを実装しています。

1) C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\FTData\noiseENU.txt を開き、そこにあるすべてのテキストをコピーします。

2) アプリケーションのコード ファイルに貼り付け、改行を "," に置き換えて、次のようなリスト初期化子を取得します。

public static List<string> _noiseWords = new List<string>{ "about", "1", "after", "2", "all", "also", "3", "an", "4", "and", "5", "another", "6", "any", "7", "are", "8", "as", "9", "at", "0", "be", "$", "because", "been", "before", "being", "between", "both", "but", "by", "came", "can", "come", "could", "did", "do", "does", "each", "else", "for", "from", "get", "got", "has", "had", "he", "have", "her", "here", "him", "himself", "his", "how", "if", "in", "into", "is", "it", "its", "just", "like", "make", "many", "me", "might", "more", "most", "much", "must", "my", "never", "no", "now", "of", "on", "only", "or", "other", "our", "out", "over", "re", "said", "same", "see", "should", "since", "so", "some", "still", "such", "take", "than", "that", "the", "their", "them", "then", "there", "these", "they", "this", "those", "through", "to", "too", "under", "up", "use", "very", "want", "was", "way", "we", "well", "were", "what", "when", "where", "which", "while", "who", "will", "with", "would", "you", "your", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };

3) 検索文字列を送信する前に、単語に分割し、次のようにノイズ ワード内の単語を削除します。

List<string> goodWords = new List<string>();
string[] words = searchString.Split(' ');
foreach (string word in words)
{
   if (!_noiseWords.Contains(word))
      goodWords.Add(word);
}

理想的な解決策ではありませんが、ノイズ ワード ファイルが変更されない限り機能するはずです。多言語サポートでは、言語ごとのリストの辞書が使用されます。

于 2009-01-30T00:12:39.790 に答える
1

ここに作業関数があります。ファイルnoiseENU.txtは からそのままコピーされます\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\FTData

    Public Function StripNoiseWords(ByVal s As String) As String
        Dim NoiseWords As String = ReadFile("/Standard/Core/Config/noiseENU.txt").Trim
        Dim NoiseWordsRegex As String = Regex.Replace(NoiseWords, "\s+", "|") ' about|after|all|also etc.
        NoiseWordsRegex = String.Format("\s?\b(?:{0})\b\s?", NoiseWordsRegex)
        Dim Result As String = Regex.Replace(s, NoiseWordsRegex, " ", RegexOptions.IgnoreCase) ' replace each noise word with a space
        Result = Regex.Replace(Result, "\s+", " ") ' eliminate any multiple spaces
        Return Result
    End Function
于 2010-01-22T22:10:53.073 に答える
1

クエリを作成する前に、ノイズ ワードを削除することもできます。言語 ID のリスト: http://msdn.microsoft.com/en-us/library/ms190303.aspx

Dim queryTextWithoutNoise As String = removeNoiseWords(queryText, ConnectionString, 1033)

Public Function removeNoiseWords (ByVal inputText As String, ByVal cnStr As String, ByVal languageID As Integer) As String

    Dim r As New System.Text.StringBuilder
    Try
        If inputText.Contains(CChar("""")) Then
            r.Append(inputText)
        Else
            Using cn As New SqlConnection(cnStr)

                Const q As String = "SELECT display_term,special_term FROM sys.dm_fts_parser(@q,@l,0,0)"
                cn.Open()
                Dim cmd As New SqlCommand(q, cn)
                With cmd.Parameters
                    .Add(New SqlParameter("@q", """" & inputText & """"))
                    .Add(New SqlParameter("@l", languageID))
                End With
                Dim dr As SqlDataReader = cmd.ExecuteReader
                While dr.Read
                    If Not (dr.Item("special_term").ToString.Contains("Noise")) Then
                        r.Append(dr.Item("display_term").ToString)
                        r.Append(" ")
                    End If
                End While
            End Using
        End If
    Catch ex As Exception
        ' ...        
    End Try
    Return r.ToString

End Function
于 2010-10-25T10:26:20.187 に答える
0

私のアプローチに似ています。

ステミングを実行する機能、速度、複数の単語の検索などのために全文索引を使用したいのですが、実際には2つのテーブルの2つのnvarchar(100)フィールドのみに索引を付けています。各テーブルは簡単に50,000行未満のままになります。

私の解決策は、テキストファイルからすべてのノイズワードを削除し、インデクサーがすべてのワードを含むインデックスをコンパイルできるようにすることでした。それはまだ数千のエントリだけで構成されています。

次に、元の投稿で説明されているように、検索文字列のスペースを置換して、CONTAINSが複数の単語で機能するようにし、単語を個別に語幹にします。

本当にうまくいくようですが、私はパフォーマンスに注意を払っています。

于 2009-02-04T14:43:09.157 に答える