Proceso de consulta en Windows Search
Este tema se organiza de la siguiente manera:
Acerca de la consulta en Windows Search
La consulta en Windows Search se basa en los cuatro enfoques siguientes:
- Sintaxis de consulta avanzada (AQS)
- Sintaxis de consulta natural (NQS)
- Lenguaje de consulta estructurado (SQL)
- Interfaces de consulta estructuradas
AQS es la sintaxis de consulta predeterminada usada por Windows Search para consultar el índice y para refinar y restringir los parámetros de búsqueda. AQS se centra principalmente en el usuario y los usuarios pueden usar para crear consultas de AQS, pero también los desarrolladores pueden usarlas para compilar consultas mediante programación. En Windows 7, se introdujo AQS canónico y se debe usar para generar consultas AQS mediante programación. En Windows 7 y versiones posteriores, una opción de menú contextual puede estar disponible en función de si se cumple una condición de AQS. Para obtener más información, vea "Obtención del comportamiento dinámico para verbos estáticos mediante la sintaxis de consulta avanzada" en Crear controladores de menú contextual. Las consultas de AQS se pueden limitar a tipos específicos de archivos, que se conocen como tipos de archivo. Para obtener más información, vea Tipos de archivo y asociaciones. Para obtener documentación de referencia sobre las propiedades pertinentes, consulte System.Kind y System.KindText.
NQS es una sintaxis de consulta más flexible que AQS y es similar al lenguaje humano. Windows Search puede usar NQS para consultar el índice si NQS está seleccionado en lugar del valor predeterminado, AQS.
SQL es un lenguaje de texto que define las consultas. SQL es común en muchas tecnologías de base de datos diferentes. Windows Search usa SQL, implementa un subconjunto de él y lo extiende agregando elementos al lenguaje. Windows Search SQL amplía la sintaxis de consulta de base de datos SQL-92 y SQL-99 estándar para mejorar su utilidad con las búsquedas basadas en texto. Todas las características de Windows Search SQL son compatibles con Windows Search en Windows XP y Windows Server 2003 y versiones posteriores. Para obtener más información sobre Windows Search SQL, vea Consulta del índice con sintaxis SQL de Windows Search y Información general sobre la sintaxis SQL de Windows Search.
Las API de consulta estructurada se describen más adelante en este tema. Para obtener documentación de referencia sobre las API de consulta estructuradas, consulte Interfaces de consulta. Las interfaces como ISearchQueryHelper ayudan a construir cadenas SQL a partir de un conjunto de valores de entrada. Esta interfaz convierte las consultas de usuario de AQS en SQL de Windows Search y especifica las restricciones de consulta que se pueden expresar en SQL, pero no en AQS. ISearchQueryHelper también obtiene una cadena de conexión OLE DB para conectarse a la base de datos de Windows Search.
Consultas locales y remotas
Puede ejecutar las consultas de forma local o remota. En el ejemplo siguiente se muestra una consulta local mediante la cláusula FROM . Una consulta local consulta solo el catálogo systemIndex local.
FROM SystemIndex
En el ejemplo siguiente se muestra una consulta remota mediante la cláusula FROM . Al agregar ComputerName, se transforma el ejemplo anterior en una consulta remota.
FROM [<ComputerName>.]SystemIndex
De forma predeterminada, Windows XP y Windows Server 2003 no tienen Windows Search instalado. Solo Windows Search 4 (WS4) proporciona compatibilidad con consultas remotas. Las versiones anteriores de Windows Desktop Search (WDS), como 3.01 y versiones anteriores, no admiten consultas remotas. Con el Explorador de Windows, puede consultar el índice local de un equipo remoto para los elementos del sistema de archivos (elementos administrados por el protocolo "file:").
Para recuperar un elemento por consulta remota, el elemento debe cumplir los siguientes requisitos:
- Sea accesible a través de la ruta de acceso de convención de nomenclatura universal (UNC).
- Existe en el equipo remoto al que tiene acceso el cliente.
- Establezca su seguridad para permitir que el cliente tenga acceso de lectura.
El Explorador de Windows tiene características para compartir elementos, incluido un recurso compartido "Público" (\\Machine\Public\...) en el Centro de redes y uso compartido, y un recurso compartido de "Usuarios" (\\Equipo\Usuarios\...) para los elementos compartidos mediante el Asistente para compartir. Después de compartir las carpetas, puede consultar el índice local especificando el nombre del equipo remoto en la cláusula FROM y una ruta de acceso UNC en el equipo remoto en la cláusula SCOPE. En el ejemplo siguiente se muestra una consulta remota mediante las cláusulas FROM y SCOPE.
SELECT System.ItemName FROM MachineName.SystemIndex WHERE SCOPE='file://MachineName/<path>'
En los ejemplos que se proporcionan aquí se usa SQL.
Introducción a la API de consulta estructurada
Una consulta estructurada proporciona la capacidad de buscar información por combinaciones booleanas de consultas sobre propiedades individuales. En este tema se describe la funcionalidad de las API y métodos de consulta estructurados más importantes. Para obtener documentación de referencia sobre las API de consulta estructuradas, consulte Interfaces de consulta.
IQueryParser
El método IQueryParser::P arse analiza una cadena de entrada de usuario y genera una interpretación en forma de IQuerySolution. Si el parámetro pCustomProperties de ese método no es NULL, se trata de una enumeración de objetos IRichChunk (uno para cada propiedad personalizada reconocida). Los otros métodos IQueryParser permiten a la aplicación establecer varias opciones, como configuración regional, un esquema, un separador de palabras y controladores para varios tipos de entidades con nombre. IQueryParser::GetSchemaProvider devuelve una interfaz ISchemaProvider para examinar el esquema cargado.
IQuerySolution : IConditionFactory
La interfaz IQuerySolution proporciona toda la información sobre el resultado de analizar una cadena de entrada. Dado que IQuerySolution también es una interfaz IConditionFactory , se pueden crear nodos de árbol de condición adicionales. El método IQuerySolution::GetQuery genera un árbol de condición para la interpretación. IQuerySolution::GetQuery también devuelve el tipo semántico.
IConditionFactory
IConditionFactory crea nodos de árbol de condición. Si el parámetro de simplificación de IConditionFactory::MakeNot es VARIANT_TRUE, se simplifica la ICondition resultante y no necesita ser un nodo de negación. Si el parámetro pSubConditions de IConditionFactory::MakeAndOr no es null, ese parámetro debe ser una enumeración de objetos ICondition y convertirse en subárboles. IConditionFactory::MakeLeaf construye un nodo hoja con un nombre de propiedad, una operación y un valor especificados. La cadena del parámetro pValueType debe ser el nombre de un tipo semántico del esquema. Si el parámetro expand es VARIANT_TRUE y la propiedad es virtual, el árbol de condición resultante suele ser una disjunción resultante de expandir la propiedad a sus componentes definidos. Si no es null, los parámetros pPropertyNameTerm, pOperatorTerm y pValueTerm deben identificar los términos que indican la propiedad, la operación y el valor.
ICondition : IPersistStream
La interfaz ICondition es un único nodo en un árbol de condiciones. El nodo puede ser un nodo de negación, un nodo AND o un nodo hoja. Para un nodo no hoja ICondition::GetSubConditions devuelve una enumeración de los subárboles. Para un nodo hoja, los métodos siguientes de ICondition devuelven los siguientes valores:
- GetComparisonInfo devuelve el nombre, la operación y el valor de la propiedad.
- GetValueType devuelve el tipo semántico del valor, que se especificó en el parámetro pszValueType de IConditionFactory::MakeLeaf.
- GetValueNormalization devuelve una forma de cadena del valor. (Si el valor ya era una cadena, este formulario se normalizará con respecto a mayúsculas y minúsculas, acentos, etc.)
- GetInputTerms devuelve información sobre qué partes de la frase de entrada generaron el nombre de propiedad, la operación y el valor.
- Clone devuelve una copia profunda de un árbol de condición.
IRichChunk
Cada objeto IRichChunk identifica un intervalo de tokens y una cadena. IRichChunk es una interfaz de utilidad que representa información sobre un intervalo (normalmente un intervalo de tokens) identificado por una posición inicial y una longitud. Esta información de intervalo incluye una cadena o un valor VARIANT.
IConditionGenerator
La aplicación proporciona la interfaz IConditionGenerator para controlar la generación de árboles de condición y reconocimiento para un tipo de entidad con nombre. Se proporciona un generador de condiciones a un IQueryParser a través de IQueryParser::SetMultiOption. IQueryParser llama a IConditionGenerator::Initialize con un ISchemaProvider para el esquema cargado actualmente. Al hacerlo, IConditionGenerator puede obtener cualquier información de esquema necesaria. Al analizar una cadena de entrada, IQueryParser llama al método IConditionGenerator::RecognizeNamedEntities de cada IConditionGenerator, de modo que se pueda notificar la aparición de entidades con nombre que reconoce en la cadena de entrada. IQueryParser puede usar la configuración regional actual y debe usar la tokenización de la entrada, ya que necesita notificar los intervalos de token de cualquier entidad con nombre.
Cuando IQueryParser está a punto de emitir un nodo hoja y el tipo semántico del valor coincide con el tipo de entidad con nombre para un IConditionGenerator, IQueryParser llama a IConditionGenerator::GenerateforLeaf con la información del nodo que se va a generar. Si IConditionGenerator devuelve S_OK, debe devolver un árbol de condiciones (que no tiene que ser un nodo hoja) e informar a IQueryParser de si desea suprimir la interpretación alternativa de la cadena que normalmente generaría como precaución.
ITokenCollection
El método ITokenCollection::NumberOfTokens devuelve el número de tokens. ITokenCollection::GetToken devuelve información sobre el token i. El principio y la longitud son posiciones de caracteres en la cadena de entrada. El texto devuelto será distinto de NULL solo si hay un texto que invalida los caracteres de la cadena de entrada. Esto se usa, por ejemplo, para invalidar un guión en la cadena de entrada con NOT cuando ese guión se encuentra en un contexto donde debe interpretarse como negación.
INamedEntityCollector
IConditionGenerator llama a INamedEntityCollector::Add para cada entidad con nombre que reconoce. Los intervalos son intervalos de tokens. Siempre debe ser el caso que beginSpan ? beginActual<endActual ? endSpan. beginSpan y endSpan pueden diferir de beginActual y endActual si la entidad con nombre comienza o termina con tokens semánticamente insignificantes, como comillas (que sin embargo están cubiertos por la entidad con nombre). El valor debe expresarse como una cadena y aparecerá posteriormente en una llamada a IConditionGenerator::GenerateForLeaf.
ISchemaProvider
La interfaz ISchemaProvider se puede usar para examinar un esquema cargado de entidades (tipos) y relaciones (propiedades). Esto es lo que hacen los métodos individuales:
- Entities devuelve una enumeración de todas las entidades (IEntity) del esquema.
- RootEntity devuelve la entidad raíz del esquema. Para un esquema plano, se devuelve el tipo principal de cada IQuerySolution .
- GetEntity busca una entidad por nombre y devuelve S_FALSE si no hay dicha entidad en el esquema.
- MetaData devuelve una enumeración de interfaces IMetaData .
IEntity
La interfaz IEntity es una entidad de esquema que representa un tipo que tiene un nombre, tiene una serie de relaciones con nombre a otros tipos (propiedades) y deriva de una entidad base. Esto es lo que hacen sus métodos individuales:
- IEntity::Relationships devuelve una enumeración de objetos IRelationship , uno para cada relación saliente de este tipo. Cada relación saliente de una entidad tiene un nombre.
- IEntity::GetRelationship busca una relación por nombre y devuelve S_FALSE si no existe dicha relación para esta entidad.
- IEntity::MetaData devuelve una enumeración de interfaces IMetaData , una para cada par de metadatos de esta entidad.
- IEntity::D efaultPhrase devuelve una frase predeterminada para facilitar la generación de una restateción de AQS o NQS de un árbol de condiciones.
IRelationship
La interfaz IRelationship representa una relación entre dos entidades: un origen y un destino. Esto es lo que hacen los métodos individuales:
- IRelationship::IsReal informa de si una relación es real. Por ejemplo, si la entidad A deriva de la entidad B y hereda una relación denominada R de ella, es posible que A todavía tenga su propia relación denominada R. Sin embargo, la relación entre A y R debe tener el mismo tipo de destino que B, y el único motivo para que exista es almacenar metadatos específicos de B. Tal relación de B se dice que no es real.
- IRelationship::Medadata devuelve una enumeración de interfaces IMetaData , una para cada par de metadatos de esta entidad.
- IRelationship::D efaultPhrase devuelve la frase predeterminada que se usará para esta relación en restatements. Cada relación tiene una frase predeterminada que lo indica para facilitar la generación de una restateción de AQS o NQS de un árbol de condiciones.
IMetaData
Los metadatos son pares clave-valor asociados a una entidad, una relación o todo el esquema. Dado que las claves no son necesariamente únicas, se puede considerar una colección de metadatos como un mapa múltiple. Se llama a IMetaData::GetData para recuperar la clave y el valor de un par de metadatos.
Escenarios de consulta
En los escenarios siguientes se describe el uso de las API de consulta estructuradas en Windows Search en escenarios de consulta comunes, como la creación de un árbol de condiciones y la consulta del índice.
Extracción de condiciones y análisis de consultas
Cuando se crea una consulta, su ámbito se define indicando al sistema dónde buscar. Esto restringe los resultados de la búsqueda. Una vez definido el ámbito, se aplica un filtro y se devuelve un conjunto de filtros. Los resultados de la búsqueda están restringidos mediante la creación de un árbol de condiciones con nodos hoja, similar a un gráfico. A continuación, se extraen esas condiciones. Un árbol de condición es una combinación booleana (AND, OR, NOT) de condiciones hoja, cada una de las cuales relaciona una propiedad, a través de una operación, con un valor. Un nodo hoja representa una restricción de una sola propiedad a un valor a través de algunas operaciones.
Una restricción de filtro requiere una expresión lógica que describa la restricción. La definición de esta expresión comienza con la interfaz ICondition , que se usa para crear un único nodo en un árbol de condiciones. Dado que solo hay una condición en el ejemplo siguiente, el árbol no cambia.
[
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);
};
Si hay más de una condición de filtro, se usan AND y otros operadores booleanos para lograr un único árbol. Los árboles AND y los árboles OR representan conjunciones y disjunciones de sus subárboles. Un árbol NOT representa la negación de su único subárbol. AQS proporciona un enfoque de texto para lograr expresiones lógicas con operadores booleanos y, a menudo, es más sencillo.
En el ejemplo siguiente, se convierte el árbol de condiciones (ICondition) en forma visual. El analizador de consultas, mediante la interfaz IQueryParser , convierte ICondition en una cadena de consulta con formato de texto enriquecido (RTF). El método IQueryParser::RestateToString devuelve el texto de la consulta, mientras que el método IQueryParser::P arse genera una interfaz IQuerySolution . En el ejemplo siguiente se muestra cómo hacer todo eso.
[
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);
};
La entrada principal de IQueryParser::P arse es una cadena de entrada de usuario que se va a analizar, pero la aplicación también puede informar al analizador de consultas de las propiedades que ha reconocido en la entrada (de la sintaxis específica de la aplicación). La salida de IQueryParser::P arse es una IQuerySolution, que proporciona toda la información relativa a esa invocación de análisis. Hay métodos para obtener la cadena de entrada, cómo se tokenizó la cadena de entrada, los errores de análisis y la consulta analizada como árbol de condiciones, representada por una ICondition. En el ejemplo siguiente se muestra ...
[
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);
}
En el ejemplo anterior, IQuerySolution::GetQuery podría obtener cualquier información sobre la consulta, incluido el texto original, los tokens que componen el texto o el árbol de condiciones. En la tabla siguiente se muestran ejemplos de posibles valores de consulta devueltos.
Ejemplos de valores de consulta devueltos | Descripción |
---|---|
author:relja OR author:tyler |
El texto de consulta que devuelve IQueryParser::RestateToString |
?author?, ?:?, ?relja?, ?OR?, ?author?, ?:?, ?tyler? |
La separación de tokens |
Un árbol de condiciones sin resolver |
El árbol de condición inicial que se devuelve no se resuelve. En un árbol de condiciones sin resolver, las referencias de fecha y hora, como date:yesterday
, no se convierten en hora absoluta. Además, las propiedades virtuales no se expanden. Las propiedades virtuales son propiedades que actúan como agregados de varias propiedades.
Por ejemplo, la consulta kind:email from:reljai
genera los siguientes árboles de condición no resueltos y resueltos. El árbol de condición sin resolver está a la izquierda y el árbol de condición resuelto está a la derecha.
El árbol resuelto se puede obtener llamando a IConditionFactory::Resolve. Sin embargo, pasar SQRO_DONT_RESOLVE_DATETIME deja sin resolver la fecha y hora. Hay ventajas en un árbol de condiciones sin resolver, ya que un árbol de condición sin resolver contiene información sobre la consulta. Cada nodo hoja apunta a los tokens devueltos por IQuerySolution::GetLexicalData, que corresponden a la propiedad, el operador y el valor cuando se usa la interfaz IRichChunk . En el ejemplo siguiente se muestra ...
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);
}
Consulta del índice
Hay varios enfoques para consultar el índice. Algunos se basan en SQL y otros se basan en AQS. También puede consultar el índice de Windows Search mediante programación mediante interfaces de consulta. Hay tres interfaces específicas para consultar el índice: ISearchQueryHelper, IRowsetPrioritization e IRowsetEvents. Para obtener información conceptual, vea Consultar el índice mediante programación.
Puede desarrollar un componente o una clase auxiliar para consultar el índice mediante la interfaz ISearchQueryHelper . Esta interfaz se implementa como una clase auxiliar para ISearchCatalogManager (e ISearchCatalogManager2) y se obtiene llamando a ISearchCatalogManager::GetQueryHelper. Para obtener información conceptual, vea Consultar el índice con ISearchQueryHelper.
ISearchQueryHelper le permite:
- Obtenga una cadena de conexión OLE DB para conectarse a la base de datos de Windows Search.
- Convierta las consultas de usuario de AQS en SQL de Windows Search.
- Especifique las restricciones de consulta que se pueden expresar en SQL, pero no en AQS.
La priorización de la indexación y los eventos de conjunto de filas se admiten en Windows 7 y versiones posteriores. Con IRowsetPrioritization hay una pila de prioridad que permite al cliente solicitar que los ámbitos usados en una consulta determinada se les dé una prioridad mayor que la normal. IRowsetEvents proporciona notificaciones de cambios en los elementos de los conjuntos de filas, incluida la adición de nuevos elementos, la eliminación de elementos y la modificación de los datos del elemento. El uso de notificaciones de eventos de conjunto de filas garantiza que los resultados de las consultas existentes estén lo más actualizados posible. Para obtener información conceptual, vea Indexación de priorización y eventos de conjunto de filas en Windows 7.
Temas relacionados