Share via


Windows Search でのクエリ 処理

このトピックは次のように整理されています。

Windows Search でのクエリは、次の 4 つの方法に基づいています。

  • 高度なクエリ構文 (AQS)
  • 自然クエリ構文 (NQS)
  • 構造化照会言語 (SQL) (Structured Query Language) (SQL)
  • 構造化クエリ インターフェイス

AQS は、Windows Search でインデックスのクエリを実行し、検索パラメーターを絞り込んで絞り込むために使用される既定のクエリ構文です。 AQS は主にユーザー向けであり、ユーザーが AQS クエリを作成するために使用できますが、開発者がプログラムでクエリを作成するために使用することもできます。 Windows 7 では、正規の AQS が導入され、プログラムによって AQS クエリを生成するために使用する必要があります。 Windows 7 以降では、AQS 条件が満たされているかどうかに基づいてショートカット メニュー オプションを使用できます。 詳細については、「 コンテキスト メニュー ハンドラーの作成」の「高度なクエリ構文を使用した静的動詞の動的動作の取得」を参照してください。 AQS クエリは、ファイルの種類と呼ばれる特定の種類のファイルに限定できます。 詳細については、「 ファイルの種類と関連付け」を参照してください。 関連するプロパティのリファレンス ドキュメントについては、「System.Kind」および「System.KindText」を参照してください。

NQS は、AQS よりも緩やかなクエリ構文であり、人間の言語に似ています。 既定の AQS ではなく NQS が選択されている場合は、Windows Search で NQS を使用してインデックスのクエリを実行できます。

SQL は、クエリを定義するテキスト言語です。 SQL は、さまざまなデータベース テクノロジで一般的です。 Windows Search では SQL を使用し、そのサブセットを実装し、言語に要素を追加して拡張します。 Windows Search SQL では、標準の SQL-92 および SQL-99 データベース クエリ構文が拡張され、テキストベースの検索での有用性が向上します。 Windows Search SQL のすべての機能は、Windows XP および Windows Server 2003 以降の Windows Search と互換性があります。 Windows Search SQL の詳細については、「Windows Search SQL 構文を使用したインデックスのクエリ」および「Windows Search SQL 構文の概要」を参照してください。

構造化クエリ API については、このトピックで後述します。 構造化クエリ API のリファレンス ドキュメントについては、「 インターフェイスのクエリ」を参照してください。 ISearchQueryHelper などのインターフェイスは、一連の入力値から SQL 文字列を構築するのに役立ちます。 このインターフェイスは、AQS ユーザー クエリを Windows Search SQL に変換し、SQL では表現できますが、AQS では表現できないクエリ制限を指定します。 ISearchQueryHelper は、Windows Search データベースに接続するための OLE DB 接続文字列も取得します。

ローカルクエリとリモートクエリ

クエリは、ローカルまたはリモートで実行できます。 FROM 句を使用したローカル クエリを次の例に示します。 ローカル クエリでは、ローカル SystemIndex カタログに対してのみクエリを実行します。

FROM SystemIndex

FROM 句を使用したリモート クエリを次の例に示します。 ComputerName を追加すると、前の例がリモート クエリに変換されます。

FROM [<ComputerName>.]SystemIndex

既定では、Windows XP と Windows Server 2003 には Windows Search がインストールされていません。 リモート クエリのサポートを提供するのは、Windows Search 4 (WS4) のみです。 以前のバージョンの Windows デスクトップ検索 (WDS) (3.01 以前など) では、リモート クエリはサポートされていません。 Windows エクスプローラーを使用すると、リモート コンピューターのローカル インデックスに対して、ファイル システム項目 ("file:" プロトコルによって処理される項目) を照会できます。

リモート クエリで項目を取得するには、項目が次の要件を満たしている必要があります。

  • 汎用名前付け規則 (UNC) パスを使用してアクセスできます。
  • クライアントがアクセスできるリモート コンピューター上に存在します。
  • クライアントが読み取りアクセスを許可するようにセキュリティを設定します。

Windows エクスプローラーには、ネットワークと共有センターの "パブリック" 共有 (\\Machine\Public\...)、共有ウィザードで共有されるアイテムの "ユーザー" 共有 (\\Machine\Users\...) など、アイテムを共有するための機能があります。 フォルダーを共有したら、FROM 句でリモート コンピューターのコンピューター名を指定し、SCOPE 句でリモート コンピューターの UNC パスを指定することで、ローカル インデックスに対してクエリを実行できます。 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 オブジェクトの列挙体です (認識されたカスタム プロパティごとに 1 つ)。 他の IQueryParser メソッドを使用すると、アプリケーションでは、ロケール、スキーマ、ワード ブレーカー、さまざまな種類の名前付きエンティティのハンドラーなど、いくつかのオプションを設定できます。 IQueryParser::GetSchemaProvider は、読み込まれたスキーマを参照するための ISchemaProvider インターフェイスを返します。

IQuerySolution : IConditionFactory

IQuerySolution インターフェイスは、入力文字列を解析した結果に関するすべての情報を提供します。 IQuerySolutionIConditionFactory インターフェイスでもあるため、追加の条件ツリー ノードを作成できます。 IQuerySolution::GetQuery メソッドは、解釈のための条件ツリーを生成します。 IQuerySolution::GetQuery はセマンティック型も返します。

IConditionFactory

IConditionFactory は 、条件ツリー ノードを作成します。 IConditionFactory::MakeNot簡略化パラメーターがVARIANT_TRUE場合、結果の ICondition は簡略化され、否定ノードである必要はありません。 IConditionFactory::MakeAndOrpSubConditions パラメーターが null でない場合、そのパラメーターは ICondition オブジェクトの列挙体であり、サブツリーになります。IConditionFactory::MakeLeaf は、指定されたプロパティ名、操作、および値を持つリーフ ノードを構築します。 pValueType パラメーターの文字列は、スキーマのセマンティック型の名前にする必要があります。 expand パラメーターがVARIANT_TRUEで、 プロパティが仮想の場合、結果の条件ツリーは通常、定義された構成要素にプロパティを展開した結果として得られる結合になります。 null でない場合、 pPropertyNameTermpOperatorTermおよび pValueTerm パラメーターは、プロパティ、操作、および値を示す用語を識別する必要があります。

ICondition : IPersistStream

ICondition インターフェイスは、条件ツリー内の 1 つのノードです。 ノードには、否定ノード、AND ノード、OR ノード、またはリーフ ノードを指定できます。 非リーフ ノード の場合、ICondition::GetSubConditions は サブツリーの列挙を返します。 リーフ ノードの場合、 ICondition の次のメソッドは次の値を返します。

  • GetComparisonInfo は、プロパティ名、操作、および値を返します。
  • GetValueType は、IConditionFactory::MakeLeafpszValueType パラメーターで指定された値のセマンティック型を返します。
  • GetValueNormalization は、値の文字列形式を返します。 (値が既に文字列の場合、この形式は大文字と小文字やアクセントなどに関して正規化されます)。
  • GetInputTerms は、 入力文のどの部分がプロパティ名、操作、および値を生成したかについての情報を返します。
  • Clone は、条件ツリーのディープ コピーを返します。

IRichChunk

IRichChunk オブジェクトは、トークンスパンと文字列を識別します。 IRichChunk は、開始位置と長さによって識別されるスパン (通常はトークンのスパン) に関する情報を表すユーティリティ インターフェイスです。 このスパン情報には、文字列や VARIANT が含まれます。

IConditionGenerator

IConditionGenerator インターフェイスは、名前付きエンティティ型の認識と条件ツリーの生成を処理するためにアプリケーションによって提供されます。 条件ジェネレーターは、IQueryParser::SetMultiOption を使用して IQueryParser に渡されます。 IQueryParser は、現在読み込まれているスキーマに対して ISchemaProvider を使用して IConditionGenerator::Initialize を呼び出します。 これにより、 IConditionGenerator は必要なスキーマ情報を取得できます。 入力文字列を解析するときに、IQueryParser は各 IConditionGenerator::RecognizeNamedEntities メソッドを呼び出して、入力文字列内で認識する名前付きエンティティの出現を報告できるようにします。 IQueryParser は現在のロケールを利用でき、名前付きエンティティのトークンスパンを報告する必要があるため、入力のトークン化を使用する必要があります。

IQueryParser がリーフ ノードを出力しようとしているときに、値のセマンティック型が IConditionGenerator の名前付きエンティティ型と一致する場合、IQueryParser は生成されるノードの情報を使用して IConditionGenerator::GenerateforLeaf を呼び出します。 IConditionGenerator がS_OKを返す場合は、条件ツリー (リーフ ノードである必要はありません) を返し、通常は予防措置として生成される代替文字列解釈を抑制するかどうかを IQueryParser に通知する必要があります。

ITokenCollection

ITokenCollection::NumberOfTokens メソッドはトークンの数を返します。ITokenCollection::GetToken、i番目のトークンに関する情報を返します。 先頭と長さは、入力文字列内の文字位置です。 返されるテキストは、入力文字列の文字をオーバーライドするテキストがある場合にのみ null 以外になります。 これは、たとえば、そのダッシュが否定として解釈されるコンテキストにある場合に、入力文字列のダッシュを NOT でオーバーライドするために使用されます。

INamedEntityCollector

IConditionGenerator は、認識された名前付きエンティティごとに INamedEntityCollector::Add を 呼び出します。 スパンはトークン スパンです。 これは常に beginSpan である必要があります。 beginActual<endActual ? endSpanbeginSpanendSpan は、名前付きエンティティが引用符などの意味的に重要でないトークン (名前付きエンティティでカバーされる) で始まる場合、 beginActual および endActual とは異なる場合があります。 値は文字列として表す必要があり、その後 、IConditionGenerator::GenerateForLeaf の呼び出しに表示されます。

ISchemaProvider

ISchemaProvider インターフェイスを使用すると、読み込まれたスキーマでエンティティ (型) とリレーション (プロパティ) を参照できます。 個々のメソッドで行われることを次に示します。

  • エンティティは、 スキーマ内のすべてのエンティティ (IEntity) の列挙を返します。
  • RootEntity はスキーマのルート エンティティを返します。 フラット スキーマの場合、すべての IQuerySolution のメイン型が返されます。
  • GetEntity はエンティティを名前で検索し、スキーマにそのようなエンティティがない場合はS_FALSEを返します。
  • MetaDataIMetaData インターフェイスの列挙を返します。

IEntity

IEntity インターフェイスは、名前を持ち、他の型 (プロパティ) との名前付きリレーションシップを多数持ち、基本エンティティから派生した型を表すスキーマ エンティティです。 個々のメソッドの実行内容を次に示します。

  • IEntity::Relationships は、この型の出力関係ごとに 1 つずつ、 IRelationship オブジェクトの列挙を返します。 エンティティの各送信関係には名前があります。
  • IEntity::GetRelationship は名前でリレーションシップを検索し、このエンティティにこのようなリレーションシップがない場合はS_FALSEを返します。
  • IEntity::MetaData は、このエンティティのメタデータ ペアごとに 1 つずつ、 IMetaData インターフェイスの列挙を返します。
  • IEntity::D efaultPhrase は、条件ツリーの AQS または NQS の再評価を容易にするために、既定のフレーズを返します。

IRelationship

IRelationship インターフェイスは、ソースと宛先の 2 つのエンティティ間のリレーションシップを表します。 個々のメソッドで行われることを次に示します。

  • IRelationship::IsReal は 、リレーションシップが実際かどうかを報告します。 たとえば、エンティティ A がエンティティ B から派生し、そこから R という名前のリレーションシップを継承する場合、A には R という名前の独自のリレーションシップが存在する可能性があります。ただし、リレーションシップ beween A と R の宛先の種類は B と同じである必要があります。存在する唯一の理由は、B に固有のメタデータを格納することです。このようなBの関係は現実とは言えない。
  • IRelationship::Medadata は、このエンティティのメタデータ ペアごとに 1 つずつ、 IMetaData インターフェイスの列挙を返します。
  • IRelationship::D efaultPhrase は、このリレーションシップに使用する既定の語句を再設定で返します。 各リレーションシップには、条件ツリーの AQS または NQS 再調整の生成を容易にするために、それを示す既定の語句があります。

IMetaData

メタデータは、エンティティ、リレーションシップ、またはスキーマ全体にそれぞれ関連付けられているキーと値のペアです。 キーは必ずしも一意であるとは限らないため、メタデータのコレクションはマルチマップと考えることができます。 IMetaData::GetData は、メタデータ ペアのキーと値を取得するために呼び出されます。

クエリシナリオ

次のシナリオでは、条件ツリーの作成やインデックスのクエリなど、一般的なクエリシナリオでの Windows Search での構造化クエリ API の使用について説明します。

条件抽出とクエリ解析

クエリが作成されると、そのスコープは、検索する場所をシステムに指示することによって定義されます。 これにより、検索結果が制限されます。 スコープが定義されると、フィルターが適用され、フィルター セットが返されます。 検索結果は、グラフと同様に、リーフ ノードを含む条件ツリーを構築することによって制限されます。 その後、これらの条件が抽出されます。 条件ツリーはリーフ条件のブール値の組み合わせ (AND、OR、NOT) であり、それぞれが操作を通じてプロパティを値に関連付けます。 リーフ ノードは、一部の操作による値に対する単一のプロパティに対する制限を表します。

フィルター制限には、制限を記述する論理式が必要です。 この式の定義は、条件ツリーに単一のノードを作成するために使用される ICondition インターフェイスから始まります。 次の例では条件が 1 つしかないため、ツリーは変更されません。

    
    [
        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 および他のブール演算子を使用して 1 つのツリーを実現します。 AND ツリーと OR ツリーは、サブツリーの結合と結合を表します。 NOT ツリーは、その単一サブツリーの否定を表します。 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);
    };

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 インデックス に対してクエリを実行することもできます。 インデックスのクエリに固有のインターフェイスは、 ISearchQueryHelperIRowsetPrioritizationIRowsetEvents の 3 つあります。 概念情報については、「 プログラムによるインデックスのクエリ」を参照してください。

ISearchQueryHelper インターフェイスを使用して、インデックスに対してクエリを実行するコンポーネントまたはヘルパー クラスを開発できます。 このインターフェイスは、ISearchCatalogManager (および ISearchCatalogManager2) のヘルパー クラスとして実装され、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 の書式設定の要件