Полнотекстовый индексатор SQL, точные совпадения и экранирование - PullRequest
0 голосов
/ 19 января 2011

Я пытаюсь заменить индекс Lucene.NET на основе анализатора ключевых слов на SQL Server 2008 R2.

У меня есть таблица, содержащая настраиваемые индексированные поля, по которым мне нужно выполнять запросы. Значение столбца индекса (см. Ниже) представляет собой комбинацию пар имя / значение пользовательских полей индекса из серии типов .NET - фактические значения извлекаются из атрибутов во время выполнения, поскольку структура неизвестна.

Мне нужно иметь возможность искать пары имен и значений, используя AND и OR, и возвращать строки, в которых совпадает запрос.

Id          Index
====================================================================
1           [Descriptor.Type]=[5][Descriptor.Url]=[/]
2           [Descriptor.Type]=[23][Descriptor.Url]=[/test]
3           [Descriptor.Type]=[25][Descriptor.Alternative]=[hello]
4           [Descriptor.Type]=[26][Descriptor.Alternative]=[hello][Descriptor.FriendlyName]=[this is a test]

Простой запрос выглядит так:

select * from Indices where contains ([Index], '[Descriptor.Url]=[/]');

Этот запрос приведет к следующей ошибке:

Msg 7630, Level 15, State 2, Line 1
Syntax error near '[' in the full-text search condition '[Descriptor.Url]=[/]'.

Итак, помня об этом, я изменил данные в столбце Index, чтобы использовать | вместо [ и ]:

select * from Indices where contains ([Index], '|Descriptor.Url|=|/|');

Теперь, когда этот запрос теперь действителен, когда я запускаю его, возвращаются все строки, содержащие Descriptor.Url и начинающиеся с /, вместо записей (в данном случае точно одной), которые точно совпадают.

Мой вопрос: как я могу избежать запроса, чтобы учесть [ и ] и гарантировать, что возвращается только точная совпадающая строка?

Более сложный запрос выглядит примерно так:

select * from Indices where contains ([Index], '[Descriptor.Type]=[12] AND ([Descriptor.Url]=[/] OR [Descriptor.Url]=[/test])');

Спасибо,
Кирон

Ответы [ 2 ]

1 голос
/ 15 февраля 2011

Ваша основная проблема заключается в использовании средства разбиения по словам SQL и синтаксиса CONTAINS.По умолчанию средства разбиения по словам SQL устраняют знаки препинания и нормализуют числа, даты, URL-адреса, адреса электронной почты и тому подобное.Это также строчные буквы и все слова.

Итак, для вашей входной строки:

[Descriptor.Type] = [5] [Descriptor.Url] = [/]

В индекс будут добавлены следующие токены (вместе с их позициями)

тип дескриптора nn5 5 url дескриптора

(примечание: nn5 - это способ упростить запросы к числам и датам в разных форматах, исходное число также индексируется в той же позиции)

Итак, как вы можете видеть, пунктуация даже не сохраняется в полном объеметекстовый индекс, и, следовательно, нет способа запросить его с помощью оператора CONTAINS.

Итак, ваше утверждение:

select * from Indices where contains ([Index], '|Descriptor.Url|=|/|'); 

будет фактически нормализовано до "URL-адреса дескриптора" запросомГенератор перед отправкой его в полнотекстовый индекс, таким образом, попадания во все записи, которые имеют «дескриптор» рядом с «url», исключая пунктуацию.

Вам нужен оператор LIKE .

0 голосов
/ 09 февраля 2011

Использование "|" поскольку ваш разделитель заставляет запрос содержимого думать об ИЛИ. Вот почему вы получаете неожиданные результаты. Вы должны быть в состоянии избежать скобки следующим образом:

SELECT * FROM Indices WHERE 
    contains ([Index], '[[]Descriptor.Type]=[[]12]') 
...