Поделиться через


Процесс запроса в Windows Search

Эта тема организована следующим образом:

Запросы в Windows Search основаны на следующих четырех подходах:

AQS — это синтаксис запросов по умолчанию, используемый в Windows Search для запроса индекса, а также для уточнения и сужения параметров поиска. AQS в основном предназначен для пользователей и может использоваться пользователями для создания запросов AQS, но также может использоваться разработчиками для создания запросов программным способом. В Windows 7 была введена каноническая служба AQS, которую необходимо использовать для программного создания запросов AQS. В Windows 7 и более поздних версиях параметр контекстного меню может быть доступен в зависимости от того, выполняется ли условие AQS. Дополнительные сведения см. в разделе "Получение динамического поведения для статических команд с помощью расширенного синтаксиса запросов" статьи Создание обработчиков контекстного меню. Запросы AQS могут быть ограничены определенными типами файлов, которые называются типами файлов. Дополнительные сведения см. в разделе Типы файлов и связи. Справочную документацию по соответствующим свойствам см. в разделах System.Kind и System.KindText.

NQS — это синтаксис запросов, который является более спокойным, чем AQS, и похож на человеческий язык. NQS может использоваться Windows Search для запроса индекса, если вместо значения по умолчанию AQS выбранА NQS.

SQL — это текстовый язык, определяющий запросы. SQL является общим для многих различных технологий баз данных. Windows Search использует SQL, реализует его подмножество и расширяет его, добавляя элементы в язык. Windows Search SQL расширяет стандартный синтаксис запросов базы данных SQL-92 и SQL-99, чтобы повысить его полезность с помощью текстовых поисковых запросов. Все функции WINDOWS Search SQL совместимы с Windows Search в Windows XP, Windows Server 2003 и более поздних версиях. Дополнительные сведения о Windows Search SQL см. в разделах Запрос индекса с помощью синтаксиса SQL Поиска Windows и Общие сведения о синтаксисе SQL Поиска Windows.

API структурированных запросов описаны далее в этом разделе. Справочную документацию по API структурированных запросов см. в разделе Интерфейсы запросов. Интерфейсы, такие как ISearchQueryHelper , помогают создавать строки SQL из набора входных значений. Этот интерфейс преобразует пользовательские запросы AQS в SQL Поиска Windows и задает ограничения запросов, которые могут быть выражены в SQL, но не в AQS. ISearchQueryHelper также получает строку подключения OLE DB для подключения к базе данных Windows Search.

Локальные и удаленные запросы

Запросы можно выполнять локально или удаленно. В следующем примере показан локальный запрос, использующий предложение FROM . Локальный запрос запрашивает только локальный каталог SystemIndex.

FROM SystemIndex

В следующем примере показан удаленный запрос с использованием предложения FROM . Добавление ComputerName преобразует предыдущий пример в удаленный запрос.

FROM [<ComputerName>.]SystemIndex

По умолчанию в Windows XP и Windows Server 2003 не установлена система Windows Search. Только Windows Search 4 (WS4) обеспечивает поддержку удаленных запросов. Предыдущие версии Windows Desktop Search (WDS), такие как 3.01 и более ранние версии, не поддерживают удаленные запросы. С помощью Windows Обозреватель можно запрашивать локальный индекс удаленного компьютера для элементов файловой системы (элементы, обрабатываемые протоколом file:).

Чтобы получить элемент с помощью удаленного запроса, он должен соответствовать следующим требованиям:

  • Будьте доступны через UNC-путь.
  • Существует на удаленном компьютере, к которому у клиента есть доступ.
  • Настройте безопасность, чтобы разрешить клиенту доступ на чтение.

Windows Обозреватель имеет функции для предоставления общего доступа к элементам, включая общий ресурс (\\Machine\Public\...) в центре управления сетью и общим доступом, а также общую папку "Пользователи" (\\Machine\Users\...) для элементов, к которым предоставлен доступ с помощью мастера общего доступа. После предоставления общего доступа к папкам можно запросить локальный индекс, указав имя компьютера удаленного компьютера в предложении FROM и UNC-путь на удаленном компьютере в предложении SCOPE. В следующем примере показан удаленный запрос, использующий предложения FROM и SCOPE.

SELECT System.ItemName FROM MachineName.SystemIndex WHERE SCOPE='file://MachineName/<path>' 

В приведенных здесь примерах используется SQL.

Общие сведения об API структурированных запросов

Структурированный запрос позволяет искать информацию по логическим сочетаниям запросов по отдельным свойствам. В этом разделе описаны функциональные возможности наиболее важных api-интерфейсов и методов структурированных запросов. Справочную документацию по API структурированных запросов см. в разделе Интерфейсы запросов.

IQueryParser

Метод IQueryParser::P arse анализирует входную строку пользователя и создает интерпретацию в виде IQuerySolution. Если параметр pCustomProperties этого метода не равен NULL, это перечисление объектов IRichChunk (по одному для каждого распознанного настраиваемого свойства). Другие методы IQueryParser позволяют приложению задавать несколько параметров, таких как языковой стандарт, схема, средство разбиения по словам и обработчики для различных типов именованных сущностей. IQueryParser::GetSchemaProvider возвращает интерфейс ISchemaProvider для просмотра загруженной схемы.

IQuerySolution: IConditionFactory

Интерфейс IQuerySolution предоставляет все сведения о результате синтаксического анализа входной строки. Так как IQuerySolution также является интерфейсом IConditionFactory , можно создать дополнительные узлы дерева условий. Метод IQuerySolution::GetQuery создает дерево условий для интерпретации. IQuerySolution::GetQuery также возвращает семантический тип.

IConditionFactory

IConditionFactory создает узлы дерева условий. Если параметр упроститьIConditionFactory::MakeNotVARIANT_TRUE, то результирующий ICondition упрощается и не должен быть узлом отрицания. Если параметр pSubConditionsобъекта IConditionFactory::MakeAndOr не имеет значения NULL, то этот параметр должен быть перечислением объектов ICondition и стать поддеревьем. IConditionFactory::MakeLeaf создает конечный узел с указанным именем свойства, операцией и значением. Строка в параметре pValueType должна быть именем семантического типа из схемы. Если параметр expand имеет VARIANT_TRUE , а свойство является виртуальным, результирующее дерево условий обычно является деъюнкцией, полученной в результате расширения свойства до его определенных составляющих. Если значение не равно NULL, параметры pPropertyNameTerm, pOperatorTerm и pValueTerm должны определять термины, указывающие свойство, операцию и значение.

ICondition: IPersistStream

Интерфейс ICondition — это один узел в дереве условий. Узел может быть узлом отрицания, узлом AND, узлом ИЛИ или конечным узлом. Для неконечного узла ICondition::GetSubConditions возвращает перечисление поддеревьев. Для конечного узла следующие методы ICondition возвращают следующие значения:

  • GetComparisonInfo возвращает имя свойства, операцию и значение.
  • GetValueType возвращает семантический тип значения, который был указан в параметре pszValueTypeобъекта IConditionFactory::MakeLeaf.
  • GetValueNormalization возвращает строковую форму значения. (Если значение уже было строкой, эта форма будет нормализована с учетом регистра, диакритических знаков и т. д.)
  • GetInputTerms возвращает сведения о том, какие части входного предложения создали имя свойства, операцию и значение.
  • Клонирование возвращает глубокую копию дерева условий.

IRichChunk

Каждый объект IRichChunk определяет диапазон маркеров и строку. IRichChunk — это служебный интерфейс, который представляет сведения о диапазоне (обычно это диапазон токенов), определяемом начальной позицией и длиной. Эти сведения о диапазоне включают строку и (или) VARIANT.

IConditionGenerator

Интерфейс IConditionGenerator предоставляется приложением для обработки распознавания и создания дерева условий для именованного типа сущности. Генератор условий предоставляется IQueryParser через IQueryParser::SetMultiOption. IQueryParser вызывает IConditionGenerator::Initialize с ISchemaProvider для текущей загруженной схемы. Это позволяет IConditionGenerator получить все необходимые сведения о схеме. При анализе входной строки IQueryParser вызывает метод IConditionGenerator::RecognizeNamedEntities каждого IConditionGenerator, чтобы можно было сообщить о вхождения именованных сущностей, которые он распознает во входной строке. IQueryParser может использовать текущий языковой стандарт и должен использовать маркеризацию входных данных, так как ему необходимо сообщать о диапазонах маркеров любых именованных сущностей.

Когда IQueryParser создает конечный узел, а семантический тип значения совпадает с типом именованной сущности для IConditionGenerator, IQueryParserer вызываетIConditionGenerator::GenerateforLeaf со сведениями для создаваемого узла. Если IConditionGenerator возвращает S_OK, он должен вернуть дерево условий (которое не обязательно должно быть конечным узлом) и сообщить IQueryParser , следует ли подавлять альтернативную интерпретацию строк, которая обычно создается в качестве меры предосторожности.

ITokenCollection

Метод ITokenCollection::NumberOfTokens возвращает количество токенов. ITokenCollection::GetToken возвращает сведения о i-мтокене. Начало и длина — это позиции символов во входной строке. Возвращаемый текст не будет иметь значение NULL, только если есть текст, переопределяющий символы из входной строки. Это используется, например, для переопределения дефиса во входной строке с параметром NOT, если этот дефис находится в контексте, где его следует интерпретировать как отрицание.

INamedEntityCollector

IConditionGenerator вызывает INamedEntityCollector::Add для каждой распознанной именованной сущности. Диапазоны — это диапазоны маркеров. Это всегда должно быть так, что начинаетсяSpan ? beginActual<endActual ? endSpan. beginSpan и endSpan могут отличаться от beginActual и endActual , если именованной сущности начинается и (или) заканчивается семантически незначительными маркерами, такими как кавычки (которые, тем не менее, охватываются именованной сущностью). Значение должно быть выражено в виде строки и впоследствии будет отображаться в вызове IConditionGenerator::GenerateForLeaf.

ISchemaProvider

Интерфейс ISchemaProvider можно использовать для просмотра загруженной схемы сущностей (типов) и связей (свойств). Вот что делают отдельные методы.

  • Сущности возвращают перечисление каждой сущности (IEntity) в схеме.
  • RootEntity возвращает корневую сущность схемы. Для плоской схемы возвращается тип main каждого IQuerySolution.
  • GetEntity находит сущность по имени и возвращает S_FALSE, если в схеме нет такой сущности.
  • MetaData возвращает перечисление интерфейсов IMetaData .

IEntity

Интерфейс IEntity — это сущность схемы, представляющая тип с именем, ряд именованных связей с другими типами (свойствами) и наследующая от базовой сущности. Вот что делают его отдельные методы:

  • IEntity::Relationships возвращает перечисление объектов IRelationship , по одному для каждого исходящего отношения этого типа. Каждое исходящее отношение сущности имеет имя.
  • IEntity::GetRelationship находит связь по имени и возвращает S_FALSE, если такой связи для этой сущности нет.
  • IEntity::MetaData возвращает перечисление интерфейсов IMetaData , по одному для каждой пары метаданных этой сущности.
  • IEntity::D efaultPhrase возвращает фразу по умолчанию для упрощения создания повторного представления AQS или NQS дерева условий.

IRelationship

Интерфейс IRelationship представляет связь между двумя сущностями: источником и назначением. Вот что делают отдельные методы.

  • IRelationship::IsReal сообщает, является ли связь реальной. Например, если сущность A является производным от сущности B и наследует от нее связь с именем R, то У A все еще может быть собственная связь С именем R. Однако отношения A и R должны иметь тот же тип назначения, что и У B, и единственная причина его существования заключается в хранении метаданных, относящихся к B. Такое отношение Б, как говорят, не является реальным.
  • IRelationship::Medadata возвращает перечисление интерфейсов IMetaData , по одному для каждой пары метаданных этой сущности.
  • IRelationship::D efaultPhrase возвращает фразу по умолчанию, используемую для этой связи в повторениях. Каждая связь имеет фразу по умолчанию, которая обозначает ее для упрощения создания повторного представления AQS или NQS дерева условий.

IMetaData

Метаданные — это пары "ключ-значение", каждая из которых связана с сущностью, связью или всей схемой. Так как ключи не обязательно являются уникальными, коллекцию метаданных можно рассматривать как мультикарту. Метод IMetaData::GetData вызывается для получения ключа и значения для пары метатданных.

Сценарии запросов

В следующих сценариях описывается использование API структурированных запросов в Windows Search в распространенных сценариях запросов, таких как создание дерева условий и запрос индекса.

Извлечение условий и анализ запросов

При создании запроса его область определяется путем указания системе, где искать. Это ограничивает результаты поиска. После определения область применяется фильтр и возвращается набор фильтров. Результаты поиска ограничиваются путем создания дерева условий с конечными узлами, похожими на граф. Затем эти условия извлекаются. Дерево условий — это логическое сочетание (AND, OR, NOT) конечных условий, каждое из которых связывает свойство с помощью операции со значением. Конечный узел представляет ограничение для одного свойства значением с помощью некоторых операций.

Для ограничения фильтра требуется логическое выражение, описывающее ограничение. Определение этого выражения начинается с интерфейса ICondition , который используется для создания одного узла в дереве условий. Так как в следующем примере существует только одно условие, дерево не меняется.

    
    [
        object,
        uuid(0FC988D4-C935-4b97-A973-46282EA175C8),
        pointer_default(unique)
    ]
    interface ICondition : IPersistStream
    {
        HRESULT GetConditionType([out, retval] CONDITION_TYPE* pNodeType);
        HRESULT GetSubConditions([in] REFIID riid, [out, retval, iid_is(riid)] void** ppv);
        [local] HRESULT GetComparisonInfo([out, annotation("__deref_opt_out")] LPWSTR *ppszPropertyName, [out, annotation("__out_opt")] CONDITION_OPERATION *pOperation, [out, annotation("__out_opt")] PROPVARIANT *pValue);
        HRESULT GetValueType([out, retval] LPWSTR* ppszValueTypeName);
        HRESULT GetValueNormalization([out, retval] LPWSTR* ppszNormalization);
        [local] HRESULT GetInputTerms([out, annotation("__out_opt")] IRichChunk** ppPropertyTerm, [out, annotation("__out_opt")] IRichChunk** ppOperationTerm, [out, annotation("__out_opt")] IRichChunk** ppValueTerm);
        HRESULT Clone([out, retval] ICondition** ppc);
    };


Если существует несколько условий фильтра, для достижения одного дерева используются операторы AND и другие логические операторы. And-trees and OR-trees представляют соединения и дисъюнкции их поддеревьев. Not-tree представляет отрицание одного поддеревья. AQS предоставляет текстовый подход к достижению логических выражений с помощью логических операторов и часто проще.

В следующем примере мы преобразуем дерево условий (ICondition) в визуальную форму. Средство синтаксического анализа запросов с помощью интерфейса IQueryParser преобразует ICondition в строку запроса в формате RTF. Метод IQueryParser::RestateToString возвращает текст запроса, а метод IQueryParser::P arse создает интерфейс IQuerySolution . В следующем примере показано, как это сделать.

    [
        object,
        uuid(2EBDEE67-3505-43f8-9946-EA44ABC8E5B0),
        pointer_default(unique)
    ]
    interface IQueryParser : IUnknown
    {
        HRESULT Parse([in] LPCWSTR pszInputString, [in] IEnumUnknown* pCustomProperties, [out, retval] IQuerySolution** ppSolution);
        HRESULT SetOption([in] STRUCTURED_QUERY_SINGLE_OPTION option, [in] PROPVARIANT const* pOptionValue);
        HRESULT GetOption([in] STRUCTURED_QUERY_SINGLE_OPTION option, [out, retval] PROPVARIANT* pOptionValue);
        HRESULT SetMultiOption([in] STRUCTURED_QUERY_MULTIOPTION option, [in] LPCWSTR pszOptionKey, [in] PROPVARIANT const* pOptionValue);
        HRESULT GetSchemaProvider([out, retval] ISchemaProvider** ppSchemaProvider);
        HRESULT RestateToString([in] ICondition* pCondition, [in] BOOL fUseEnglish, [out] LPWSTR* ppszQueryString);
        HRESULT ParsePropertyValue([in] LPCWSTR pszPropertyName, [in] LPCWSTR pszInputString, [out, retval] IQuerySolution** ppSolution);
        HRESULT RestatePropertyValueToString([in] ICondition* pCondition, [in] BOOL fUseEnglish, [out] LPWSTR* ppszPropertyName, [out] LPWSTR* ppszQueryString);
    };

Main входные данные IQueryParser::P arse — это строка ввода пользователя для анализа, но приложение также может сообщить средству синтаксического анализа запросов о любых свойствах, распознаваемых во входных данных (из синтаксиса конкретного приложения). Выходные данные IQueryParser::P arse — это IQuerySolution, которое предоставляет все сведения, относящиеся к этому вызову синтаксического анализа. Существуют методы получения входной строки, способа маркеризации входной строки, ошибок синтаксического анализа и проанализированного запроса в виде дерева условия, представленного ICondition. В следующем примере показана ...

    [
        object,
        uuid(D6EBC66B-8921-4193-AFDD-A1789FB7FF57),
        pointer_default(unique)
    ]
    interface IQuerySolution : IConditionFactory
    {
        [local] HRESULT GetQuery([out, annotation("__out_opt")] ICondition** ppQueryNode, [out, annotation("__out_opt")] IEntity** ppMainType);
        HRESULT GetErrors([in] REFIID riid, [out, retval, iid_is(riid)] void** ppParseErrors);
        [local] HRESULT GetLexicalData([out, annotation("__deref_opt_out")] LPWSTR* ppszInputString, [out, annotation("__out_opt")] ITokenCollection** ppTokens, [out, annotation("__out_opt")] LCID* pLocale, [out, annotation("__out_opt")] IUnknown** ppWordBreaker);
    }    

    

В предыдущем примере IQuerySolution::GetQuery мог получить любые сведения о запросе, включая исходный текст, маркеры, составляющие текст, или дерево условий. Примеры возможных возвращаемых значений запроса приведены в следующей таблице.

Примеры возвращаемых значений запроса Описание
author:relja OR author:tyler Текст запроса, возвращаемый IQueryParser::RestateToString
?author?, ?:?, ?relja?, ?OR?, ?author?, ?:?, ?tyler? Разделение токенов
дерево неразрешенных условий Дерево неразрешенных условий

 

Исходное дерево условий, которое возвращается, не разрешено. В дереве неразрешенных условий ссылки на дату и время, такие как date:yesterday, не преобразуются в абсолютное время. Кроме того, виртуальные свойства не расширяются. Виртуальные свойства — это свойства, которые действуют как агрегаты нескольких свойств.

Например, запрос kind:email from:reljai создает следующие неразрешенные и разрешенные деревья условий. Дерево неразрешенных условий находится слева, а дерево разрешенных условий — справа.

Неразрешенные и разрешенные деревья условий

Разрешенное дерево можно получить, вызвав IConditionFactory::Resolve. Однако передача SQRO_DONT_RESOLVE_DATETIME оставляет дату и время неразрешенными. Дерево неразрешенных условий имеет преимущества, так как дерево неразрешенных условий содержит сведения о запросе. Каждый конечный узел указывает на маркеры, возвращаемые IQuerySolution::GetLexicalData, которые соответствуют свойству, оператору и значению при использовании интерфейса IRichChunk . В следующем примере показана ...

    interface ITokenCollection : IUnknown
    {
        HRESULT NumberOfTokens(ULONG* pCount);
        HRESULT GetToken([in] ULONG i, [out, annotation("__out_opt")] ULONG* pBegin, [out, annotation("__out_opt")] ULONG* pLength, [out, annotation("__deref_opt_out")] LPWSTR* ppsz);
    };

ICondition:: GetInputTerms([out, annotation("__out_opt")] 
IRichChunk** ppPropertyTerm, [out, annotation("__out_opt")] 
IRichChunk** ppOperationTerm, [out, annotation("__out_opt")] 
IRichChunk** ppValueTerm);

    interface IRichChunk : IUnknown
    {
        HRESULT GetData([out, annotation("__out_opt")] ULONG* pFirstPos, [out, annotation("__out_opt")] ULONG* pLength, [out, annotation("__deref_opt_out")] LPWSTR* ppsz, [out, annotation("__out_opt")] PROPVARIANT* pValue);
    }

Запрос к индексу

Существует несколько подходов к запросу индекса. Некоторые из них основаны на SQL, а другие — на AQS. Вы также можете запросить индекс Windows Search программным способом с помощью интерфейсов запросов. Существует три интерфейса, которые относятся к запросу индекса: ISearchQueryHelper, IRowsetPrioritization и IRowsetEvents. Основные сведения см. в разделе Запрос индекса программным способом.

Вы можете разработать компонент или вспомогательный класс для запроса индекса с помощью интерфейса ISearchQueryHelper . Этот интерфейс реализуется как вспомогательный класс для ISearchCatalogManagerISearchCatalogManager2) и получается путем вызова ISearchCatalogManager::GetQueryHelper. Основные сведения см. в статье Запрос индекса с помощью ISearchQueryHelper.

ISearchQueryHelper позволяет:

  • Получите строку подключения OLE DB для подключения к базе данных Windows Search.
  • Преобразование пользовательских запросов AQS в Windows Search SQL.
  • Укажите ограничения запросов, которые можно выразить в SQL, но не в AQS.

Индексирование приоритетов и событий набора строк поддерживается в Windows 7 и более поздних версиях. При использовании IRowsetPrioritization существует стек приоритета, который позволяет клиенту запрашивать, чтобы области, используемые в определенном запросе, были выше обычного приоритета. IRowsetEvents предоставляет уведомления об изменениях элементов в наборах строк, включая добавление новых элементов, удаление элементов и изменение данных элементов. Использование уведомлений о событиях набора строк гарантирует, что результаты для существующих запросов будут максимально актуальными. Основные сведения см. в разделе Индексирование приоритетов и события набора строк в Windows 7.

Индексирование, запросы и уведомления в Windows Search

Что входит в индекс

Процесс индексирования в Windows Search

Процесс уведомлений в Windows Search

Требования к форматированию URL-адресов