Отбрасывание шумовых слов в полнотекстовой индексации SQL Server 2005 - PullRequest
2 голосов
/ 22 января 2009

В довольно типичном сценарии у меня в веб-приложении есть текстовое поле «Поиск», в котором пользовательский ввод передается непосредственно в хранимую процедуру, которая затем использует полнотекстовое индексирование для поиска по двум полям в двух таблицах, которые объединяются с использованием соответствующие ключи.

Я использую предикат CONTAINS для поиска в полях. Перед передачей строки поиска я делаю следующее:

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

Замена замка на "*" ИЛИ "замок *" , например. Это необходимо, потому что я хочу, чтобы люди могли искать на cas и получать результаты для castle .

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

Проблема в том, что теперь, когда я добавил в конец каждого слова подстановочный знак, к шумовым словам (например, * ) также добавлен подстановочный знак, и, следовательно, он больше не сбрасывается. Это означает, что поиск в замке вернет элементы со словами, такими как theatre и т. Д.

Первым делом я подумал об изменении ИЛИ на И, но, похоже, он просто не возвращает совпадений, если в запросе используется слово с шумом.

Все, чего я пытаюсь добиться, - это позволить пользователю вводить несколько слов, разделенных пробелами, которые представляют либо полноту, либо префикс слов, по которым он ищет, в любом порядке - и отбрасывать шумовые слова, такие как от их ввода (иначе, когда они ищут замок , они получают большой список предметов с результатом, который им нужен где-то в середине списка.

Я мог бы пойти дальше и реализовать свою собственную процедуру удаления шумовых слов, но, похоже, что-то, с чем должна справиться полнотекстовая индексация.

Благодарен за любую помощь!

Джейми

Ответы [ 5 ]

5 голосов
/ 28 января 2009

Шумовые слова удаляются перед сохранением индексации. Поэтому невозможно написать запрос, который выполняет поиск по стоп-слову. Если вы ДЕЙСТВИТЕЛЬНО хотите включить это поведение, вам нужно отредактировать список стоп-слов. (http://msdn.microsoft.com/en-us/library/ms142551.aspx) и затем перестройте свой индекс.

1 голос
/ 25 октября 2010

Вы также можете удалить шумовые слова ДО выполнения запроса. Список идентификаторов языков: http://msdn.microsoft.com/en-us/library/ms190303.aspx

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

Открытая функция removeNoiseWords (ByVal inputText As String, ByVal cnStr As String, ByVal languageID как целое число) как строка

    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
1 голос
/ 23 января 2010

Вот рабочая функция. Файл 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
1 голос
/ 30 января 2009

У меня был тот же вопрос, и после тщательного поиска я пришел к выводу, что хорошего решения нет.

В качестве компромисса я внедряю решение для перебора:

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);
}

Не идеальное решение, но должно работать до тех пор, пока файл шумовых слов не изменится. Многоязычная поддержка будет использовать словарь списков по языку.

0 голосов
/ 04 февраля 2009

Аналогично моему подходу.

Несмотря на то, что я хочу использовать полнотекстовое индексирование для его способности выполнять обрезку, его скорость и поиск по нескольким словам и т. Д., Я фактически индексирую только пару полей nvarchar (100) в двух таблицах. Каждая таблица легко останется ниже 50 000 строк.

Мое решение состояло в том, чтобы удалить все шумовые слова из текстового файла и позволить индексатору составить индекс, включая все слова. Он все еще состоит из нескольких тысяч записей.

Затем я заменяю пробелы в строке поиска, как описано в моем исходном сообщении, чтобы заставить CONTAINS работать с несколькими словами и подбирать слова по отдельности.

Кажется, работает очень хорошо, но я буду пристально следить за производительностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...