Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

ソースのフィルタ処理

フィルタを使用して、iKnow クエリに供給されるソースを含めたり除外したりすることができます。ドメイン内にロードされたすべてのソースに対してクエリを実行する必要がない場合も多くあります。フィルタにより、フィルタ条件を満たすソースのみにクエリ範囲を制限することが可能です。フィルタは、ソース内にあるエンティティ、またはソース自体に関連付けられた一部の情報 (メタデータ) のいずれかに基づいてソースを選択します。フィルタは常にソース全体の包含または除外を行って、フィルタを使用する各クエリ内にて指定されます。

サポートされるフィルタ

iKnow は事前定義されたフィルタを多く備えているほか、ユーザが独自のフィルタを簡単に定義できる機能を装備しています。

  • ソース ID : SourceIdFilter および ExternalIdFilter では、ソースの ID に基づいてソースを選択できます。iKnow はソース・インデックス作成プロセスの一部としてこれらの値を割り当てます。

  • ランダム・ソース : RandomFilter では、ドメインのソースのランダム・サンプルを選択できます。このサンプルは、ソースの整数または合計ソースのパーセンテージとして指定することができます。

  • ソース・コンテンツ : SentenceCountFilter では、ソース内の文の最小数や最大数に基づいてソースを選択できます。iKnow はインデックス作成プロセスの一部として、ソース内の文をカウントします。

  • エンティティの一致 : iKnow では、各ソースにあるエンティティ (概念と相関) に基づいてソースを選択可能なフィルタをいくつか用意しています。DictionaryMatchFilter では、ソース・コンテンツとディクショナリが一致する最小数や最大数に基づいたソースのフィルタ処理が可能です (このフィルタは非推奨の SimpleMatchFilter に代わるものです)。DictionaryTermMatchFilter および DictionaryItemMatchFilter では、同種のディクショナリ・マッチングを使用してソースのフィルタ処理が可能ですが、ディクショナリ全体ではなく、ディクショナリのコンポーネントに対して一致セットを制限します。これらのディクショナリ・フィルタでは、$$$IKPMATSTANDARDIZEDFORM ドメイン・パラメータが指定された場合に、オプションで標準化形式マッチングを実行できます。

    ContainsEntityFilter では、(ディクショナリのエンティティ定義ではなく) エンティティのリストを直接指定して、ソースのフィルタ処理を行うことができます。また、ContainsEntityFilter では、リストされたエンティティと類似したエンティティで、ソースのフィルタ処理を任意で行うこともできます。ContainsRelatedEntitiesFilter では、関連付けする必要のある 2 つ以上のエンティティのリストを指定して、ソースのフィルタ処理を行うことができます。つまり、それらのエンティティは同じパス (既定) または同じ CRC のいずれかで出現する必要があります。また、ContainsRelatedEntitiesFilter では、リストされたエンティティと類似した関連エンティティで、ソースのフィルタ処理を任意で行うこともできます。

  • インデックス作成日メタデータ : iKnow では、すべてのソースに対して 1 つのメタデータ・フィールド (DateIndexed フィールド) が自動で提供されます。iKnow はソース・インデックス作成プロセスの一部として、このフィールド値を割り当てます。SimpleMetadataFilter の使用により、このフィールドでは、iKnow によってインデックスが作成された日付と時刻に基づいてソースを選択できます。

  • ユーザ定義メタデータ : iKnow では、SimpleMetadataFilter を使用することで、ソースに関連付けたデータ値に基づいてソースを選択するフィルタを定義できます。

  • SQL クエリ : SqlFilter では、SQL クエリの結果に基づいてソースを選択できます。

GroupFilter を使用すれば、定義するフィルタの結果を論理的に組み合わせることができます。

ソースの ID によるフィルタ処理

最も基本的なソース・フィルタを使用して、フィルタ処理後の結果セットに含めたい各ソースのソース ID または外部 ID を提供することにより、クエリに供給するソースを制限します。

外部 ID でフィルタ処理

ExternalIdFilter には、外部 ID が %List 構造にリストされているソースが含まれます。このリスト内の有効な外部 ID でない要素や重複する外部 ID といった要素は、通知なしで無視されます。

以下の例では、ソースを外部 ID でフィルタ処理します。Aviation.Event ソースの外部 ID は単語 “Accident” または “Incident” のいずれかを含んでいます。このフィルタは、外部 ID が単語 “Incident” を含むソースのみを含んでいます。それから、フィルタ処理されたソースの詳細をリストします。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
  IF ##class(%iKnow.Configuration).Exists("myconfig") {
         SET cfg=##class(%iKnow.Configuration).Open("myconfig") }
  ELSE { SET cfg=##class(%iKnow.Configuration).%New("myconfig",0,$LISTBUILD("en"),"",1)
         DO cfg.%Save() }
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 100 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineExtIdFilter
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,100)
  SET i=1
  SET extlist=$LB("")
  WHILE $DATA(result(i)) {
        SET extId = $LISTGET(result(i),2)
        IF $PIECE(extId,":",3)="Incident" {
        SET extlist=extlist_$LB(extId) }
        SET i=i+1
  }
  SET filt=##class(%iKnow.Filters.ExternalIdFilter).%New(domId,extlist) 
SourceCountQuery
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
ApplyExtIdFilter
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
  WRITE "The Id filter includes ",numSrcFD," sources:",!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,100,filt)
       SET j=1
       WHILE $DATA(result(j)) {
         SET intId = $LISTGET(result(j),1)
         SET extId = $LISTGET(result(j),2)
         WRITE intId," ",extId,!
         SET j=j+1
      }
      WRITE "End of list"

ソース ID でフィルタ処理

SourceIdFilter には、ソース ID が %List 構造にリストされているソースが含まれます。ソース ID は整数値です。これらは任意の順序でリストできます。このリスト内の有効なソース ID でない要素や重複するソース ID といった要素は、通知なしで無視されます。

以下の例では、ソースとして SQL レコードを使用して、複数のソースをソース ID でフィルタ・インします。このデータ・セットのソース ID は 1 から 100 までの数字となります。SourceIdFilter では、5 つのソース ID の包含を指定していますが、それらのソース ID の内で 3 つだけがテーブルのレコードに対応しています。したがって、フィルタ処理されたソース数は合計で 3 になります。

DefineAFilter
  SET srclist=$LB(10,14,74,110,2799)
  SET filt=##class(%iKnow.Filters.SourceIdFilter).%New(domId,srclist)
SourceCounts
  SET numsrc = ##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
     WRITE "The ",dname," domain contains ",numsrc," sources",!
 SET numfsrc = ##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
     WRITE "Source count after source Id filtering: ",numfsrc

iKnow.Filters.Filter クラスは %iKnow.Filters.SourceIdRangeFilter サブクラスを含んでいます。以下の例では、ソースの範囲をソース ID でフィルタ処理します。これは、ソース ID が 5 以上 10 以下であるソースを返します。

  SET filt=##class(%iKnow.Filters.SourceIdRangeFilter).%New(domId,5,10)

フィルタ処理によるソースからのランダムな選択

%iKnow.Filters.RandomFilterOpens in a new tab を使用して、ソースのランダム・サンプルを選択できます。ランダム・サンプルでは、ソースの管理可能サブセットに対するテストが可能になります。また、ソース (またはそれらのサブセット) を “トレーニング” および “テスト” のセットに分割することもできます。その場合は、“トレーニング” セットを使用して、iKnow 分析 (ディクショナリの一致、ソースのカテゴリなど) を定義してから、“テスト” セットを使用して、それらの分析がどの程度他のデータ・セットに当てはまるか判定することになります。これにより、特定のデータ・セットに対する分析の “重複適合” を防ぐことができます。

以下の 2 つの方法で、ランダム・サブセットのサイズを指定できます。

  • パーセンテージとして: パーセンテージを (0 ~ 1 の範囲の小数で) 指定すると、このフィルタは指定ドメイン (またはドメインのフィルタ処理されたサブセット) 内のインデックス付けされたソースに関するパーセンテージを返します。例えば、“.5” と指定すると、ドメイン内のソースの 50% がフィルタ結果に含まれます。半分は切り上げられるため、5 つのソースの 50% では 3 つのソースになります。100% は、適切な数値の小数桁を付けて、“.999” と指定します。このフィルタは必要な数のソースをランダムに選択します。

  • 整数として: 整数を指定すると、このフィルタは指定ドメイン (またはドメインのフィルタ処理されたサブセット) 内のインデックス付けされたソースの数を返します。例えば、値を “7” にすると、ドメイン内の 7 つのソースがフィルタ結果に含まれます。このフィルタは指定された数のソースをランダムに選択します。

以下の例では、50 個のソースの内 33% をランダムに選択して、17 個のソースを返します。このサンプルを繰り返し実行すると、異なるソースがランダムにサンプリングされるのを確認できます。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
  IF ##class(%iKnow.Configuration).Exists("myconfig") {
         SET cfg=##class(%iKnow.Configuration).Open("myconfig") }
  ELSE { SET cfg=##class(%iKnow.Configuration).%New("myconfig",0,$LISTBUILD("en"),"",1)
         DO cfg.%Save() }
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineAFilter
  SET filt=##class(%iKnow.Filters.RandomFilter).%New(domId,.33)
SampledSourceQueries
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
  WRITE "Of these ",numSrcD," sources ",numSrcFD," were sampled:",!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,20,filt)
  SET i=1
  WHILE $DATA(result(i)) {
     SET intId = $LISTGET(result(i),1)
     SET extId = $LISTGET(result(i),2)
     WRITE "sample #",i," is source ",intId," ",extId,!
     SET i=i+1 } 
     WRITE "End of list"

以下の例では、ドメインのソースをソース ID によりフィルタ処理して、11 個のソースを返します。さらに、ランダム・フィルタの定義時において、このソースに ID フィルタを指定します。したがって、ランダム・フィルタはこれらのソース ID でフィルタ処理されたソースの内の 3 つを返します。このサンプルを繰り返し実行すると、異なるソースがランダムにサンプリングされるのを確認できます。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
  IF ##class(%iKnow.Configuration).Exists("myconfig") {
         SET cfg=##class(%iKnow.Configuration).Open("myconfig") }
  ELSE { SET cfg=##class(%iKnow.Configuration).%New("myconfig",0,$LISTBUILD("en"),"",1)
         DO cfg.%Save() }
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineSourceIdFilter
  SET srclist=$LB(1,3,5,7,9,11,13,15,17,21,23)
  SET idfilt=##class(%iKnow.Filters.SourceIdFilter).%New(domId,srclist)
SourceCounts
  SET numsrc = ##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
     WRITE "The ",dname," domain contains ",numsrc," sources",!
 SET numfsrc = ##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,idfilt)
     WRITE "Source count after source Id filtering: ",numfsrc,!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,20,idfilt)
  SET i=1
  WHILE $DATA(result(i)) {
     SET intId = $LISTGET(result(i),1)
     WRITE intId," "
     SET i=i+1 } 
     WRITE !,"End of list",! 
DefineRandomFilter
  SET rfilt=##class(%iKnow.Filters.RandomFilter).%New(domId,3,idfilt)
RandomSample
  SET numrsrc=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,rfilt)
  WRITE "From ",numfsrc," sources ",numrsrc," are randomly sampled:",!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,20,rfilt)
  SET j=1
  WHILE $DATA(result(j)) {
     SET intId = $LISTGET(result(j),1)
     WRITE intId," "
     SET j=j+1 } 
     WRITE !,"End of list",! 

文の数によるフィルタ処理

iKnow では、ソース・テキストがに分割されます。以下の例は、文の数が 75 未満のソースをフィルタにより除外します。ソースの合計数を返してから、フィルタを使用して 75 個以上の文を含むソースの合計数を返し、次に再度フィルタを使用して、これらの各ソースの文の数を返します。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
  IF ##class(%iKnow.Configuration).Exists("myconfig") {
         SET cfg=##class(%iKnow.Configuration).Open("myconfig") }
  ELSE { SET cfg=##class(%iKnow.Configuration).%New("myconfig",0,$LISTBUILD("en"),"",1)
         DO cfg.%Save() }
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineAFilter
  SET filt=##class(%iKnow.Filters.SentenceCountFilter).%New(domId)
  SET nsent=75
  DO filt.MinSentenceCountSet(nsent)
SourceSentenceQueries
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The domain contains ",numSrcD," sources",!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
  WRITE "Of these ",numSrcD," sources ",numSrcFD," contain ",nsent," or more sentences:",!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,50,filt)
  SET i=1
  WHILE $DATA(result(i)) {
     SET numSentS = ##class(%iKnow.Queries.SentenceAPI).GetCountBySource(domId,result(i))
     SET intId = $LISTGET(result(i),1)
     SET extId = $LISTGET(result(i),2)
     WRITE "source ",intId," ",extId
     WRITE " has ",numSentS," sentences",!
     SET i=i+1 } 
     WRITE i-1," sources listed"

文の最小数と最大数の両方を使用してフィルタするには、両方のインスタンス・メソッドを呼び出します。以下のフィルタは、10 個以上 25 個以下の文を含むソースを選択します。

MinMaxFilter
  SET min=10
  SET filt=##class(%iKnow.Filters.SentenceCountFilter).%New(domId)
  DO filt.MinSentenceCountSet(min)
  DO filt.MaxSentenceCountSet(min+15)

エンティティ一致によるフィルタ処理

以下のエンティティ・フィルタが用意されています。

  • ContainsEntityFilter : エンティティの指定リストを使用して、ソースをフィルタ処理しますが、少なくとも 1 つのエンティティがソース内で出現する必要があります。また、ContainsEntityFilter では、リストされたエンティティと類似したエンティティで、ソースのフィルタ処理を任意で行うこともできます。

  • ContainsRelatedEntitiesFilter : 関連付けする必要のある 2 つ以上のエンティティの指定リストを使用して、ソースのフィルタ処理を行います。つまり、それらのエンティティは同じパス (フィルタの既定) または同じ CRC のいずれかで出現する必要があります。また、ContainsRelatedEntitiesFilter では、リストされたエンティティと類似した関連エンティティで、ソースのフィルタ処理を任意で行うこともできます。

  • DictionaryMatchFilter : エンティティのリストを含む 1 つ以上のディクショナリを使用して、ソースのフィルタ処理を行います。既定により、少なくともそれらのエンティティの内の 1 つは、ソース内に出現する必要があります。必要に応じて、それらのエンティティ一致について指定した最小数が、選択されるソースに対して出現する必要があります。また、ディクショナリ・マッチングでは、$$$IKPMATSTANDARDIZEDFORM ドメイン・パラメータ が現在のドメインで指定された場合、標準化形式マッチングもサポートします。

ディクショナリ一致によるフィルタ処理

%iKnow.Filters.DictionaryMatchFilterOpens in a new tab クラスにより、1 つ以上のユーザ定義ディクショナリのコンテンツに基づいて、ソースを選択することができます。また、iKnow では、ディクショナリ用語のリストに対する (%iKnow.Filters.DictionaryTermMatchFilterOpens in a new tab)、またはディクショナリ項目のリストに対する (%iKnow.Filters.DictionaryItemMatchFilterOpens in a new tab) マッチングによるフィルタ処理もサポートしています。

以下の簡単な例では、2 番目のパラメータにより、ディクショナリ 1 つのみの適用が指定されていますが、複数のディクショナリも %List の要素として指定できます。3 番目のパラメータが既定の 1 に設定されています。つまり、任意のディクショナリ項目の単独一致により、包含するためのソースを選択しています。これをさらに高く設定して、ディクショナリの項目が膨大にあることにより、または膨大なテキストを含むソースのクエリにより、単一のディクショナリ一致が意味のあるものではなく、偶然の産物となる可能性があるソース選択を避ける必要性が生じる場合もあります。4 番目のパラメータは既定値 (-1) を採用することで、最大一致数制限をなくしています。最大パラメータが最少パラメータより小さい場合、ディクショナリ一致に関係なく、すべてのソースがフィルタにより選択されます。5 番目のパラメータも既定値を採用していますが、マッチングは一致スコアではなく、一致の数に基づいています。6 番目のパラメータは ensureMatched フラグです。ここでは ensureMatched=2 なので、フィルタのインスタンス化により、フィルタ呼び出しのたびに使用される静的な一致結果を生成します。これを使用することをお勧めします。フィルタのインスタンス化後にディクショナリが変更された場合、ensureMatched を 1 に設定する必要があります。ensureMatched=1 では、毎回フィルタが呼び出される前にマッチングを行うことで、ディクショナリ・コンテンツの変更が考慮されます。ただし、ensureMatched=1 を使用すると処理速度が大幅に落ちてしまうおそれがあります。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
CreateDictionary
  SET dictname="EngineTerms"
  SET dictdesc="A dictionary of aviation engine terms"
  SET dictId=##class(%iKnow.Matching.DictionaryAPI).CreateDictionary(domId,dictname,dictdesc)
  IF dictId=-1 {WRITE "Dictionary ",dictname," already exists",!
                GOTO ResetForNextTime }
  ELSE {WRITE "created dictionary ",dictId,!}
PopulateDictionaryItem1
   SET itemId=##class(%iKnow.Matching.DictionaryAPI).CreateDictionaryItem(domId,dictId,
       "engine parts",domId_dictId_1)
     SET term1Id=##class(%iKnow.Matching.DictionaryAPI).CreateDictionaryTerm(domId,itemId,
         "piston")
     SET term2Id=##class(%iKnow.Matching.DictionaryAPI).CreateDictionaryTerm(domId,itemId,
         "cylinder")
     SET term2Id=##class(%iKnow.Matching.DictionaryAPI).CreateDictionaryTerm(domId,itemId,
         "crankshaft")
     SET term2Id=##class(%iKnow.Matching.DictionaryAPI).CreateDictionaryTerm(domId,itemId,
         "camshaft")
DefineAFilter
  SET filt=##class(%iKnow.Filters.DictionaryMatchFilter).%New(domId,$LB(dictId),1,,,2)
SourceCountQuery
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
SourcesFilteredByDictionaryMatch
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
  WRITE "Of these ",numSrcD,", ",numSrcFD," match the ",dictname," dictionary:",!!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,50,filt)
  SET i=1
  WHILE $DATA(result(i)) {
     SET intId = $LISTGET(result(i),1)
     SET extId = $LISTGET(result(i),2)
     WRITE "dictionary matches ",intId," ",extId,!
     SET i=i+1 }
  WRITE !,i-1," sources included by dictionary match",!
ResetForNextTime
  IF dictId = -1 {
     SET dictId=##class(%iKnow.Matching.DictionaryAPI).GetDictionaryId(domId,dictname)}
  SET stat=##class(%iKnow.Matching.DictionaryAPI).DropDictionary(domId,dictId)
  IF stat {WRITE "deleted dictionary ",dictId,! }
  ELSE    { WRITE "DropDictionary error ",$System.Status.DisplayError(stat) }  

インデックス作成日メタデータによるフィルタ処理

すべての iKnow ソースには、DateIndexed メタデータ・フィールドが割り当てられます。このフィールドの値は、iKnow によってソースのインデックスが作成された日付と時刻になり、協定世界時形式 (UTC) で $HOROLOG 形式で示されます。これは $ZTIMESTAMP の時刻と同じになりますが、DateIndexed には秒数の小数部は含まれません。

DateIndexed を使用してフィルタを作成し、iKnow がソースをロードした日時に基づいてソースを含めたり除外したりすることができます。特定の日付と時刻を使用してフィルタ処理したり、特定の日付 (その日付内のすべての時刻値を含む) についてフィルタ処理できます。また、BETWEEN ロジックを使用すると、日付の範囲についてフィルタ処理できます。

以下の例では、今日ロードされたソースについてフィルタ処理しています。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineAFilter
  SET tday = $PIECE($ZTIMESTAMP,",",1)
  SET filt=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,"DateIndexed","=",tday)
DateIndexedValue
  WRITE "Today is ",$PIECE($ZTIMESTAMP,",",1),!
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,50)
  SET i=1
  WHILE $DATA(result(i)) {
     SET srcId = $LISTGET(result(i),1)
     SET extId = $LISTGET(result(i),2)
     SET idate = ##class(%iKnow.Queries.MetadataAPI).GetValue(domId,"DateIndexed",extId)
     WRITE "Source ",srcId," was indexed ",idate,!
     SET i=i+1 }
SourceSentenceQueries
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt)
  WRITE "Of these sources ",numSrcFD," were indexed today"

ユーザ定義メタデータによるフィルタ処理

iKnow におけるデータとは、iKnow が処理してインデックスを作成するソースのコンテンツです。また、iKnow におけるメタデータとは、iKnow がインデックスを作成するデータ以外の、ソースに関連付けられた任意のデータです。iKnow メタデータを使用して、iKnow データを識別します。メタデータ・フィルタはメタデータ・フィールドの値を使用して、クエリに供給するソースを判別します。

Note:

iKnow の “メタデータ” の定義では、データ本来の性質ではなく、データの使用方法を説明します。この概念は、Caché ソフトウェアの他の部分でメタデータという言葉が意味するものとは多少異なります。

iKnow は、クエリ API とは独立した、既定のメタデータ管理システムを提供します。%iKnow.Queries.MetadataAPIOpens in a new tab クラスと付随する %iKnow.Filters.SimpleMetadataFilterOpens in a new tab は、基本的なメタデータ・フィルタの実装を提供します。カスタムのメタデータ API を実装したい場合は、(最低でも) %iKnow.Queries.MetadataIOpens in a new tab インタフェースを実装し、次のように "MetadataAPI" ドメイン・パラメータとしてクラスを登録します : DO domain.SetParameter("MetadataAPI","Your.Metadata.Class")。後述の例では %iKnow.Filters.SimpleMetadataFilterOpens in a new tab クラスを使用しています。

Caché SQL では、SQL テーブルの各レコードが 1 つの iKnow ソースを構成します。ProcessList()Opens in a new tab メソッド (レコードが少数の場合) または AddListToBatch()Opens in a new tab メソッド (レコードが多数の場合) を使用して、リスタ・パラメータを定義します。

  • iKnow 外部 ID のコンポーネントとして RowID フィールドを定義します。iKnow はまた、各行のソース ID を一意の整数値で生成します。この iKnow ソース ID は、RowId や他の SQL 識別子の値からは完全に独立しています。

  • iKnow データとしてインデックスを作成するデータ・フィールドとして、テキスト文字列を含む 1 つまたは複数のフィールドを定義します。

  • iKnow メタデータ・フィールドとして 1 つまたは複数のフィールドを定義します。iKnow はこのメタデータ・フィールドの値を使用して、iKnow クエリのソースを選択できます。

データ・フィールドの 1 つとメタデータ・フィールドの両方に同じフィールドを指定できることに注意してください。また、オプションとして、メタデータ・フィールドに対応する metakey フィールドも定義できます。

これを、以下の例に示します。Aviation.Event テーブルは NarrativeFull テキスト・フィールドの他、各種のフィールドを含んでいます。この例では、InjuriesTotal がメタデータ・フィールドとして使用されています。メタデータ・フィールドは 3 つのフィルタで使用されています。その中の 2 つの等値フィルタは InjuriesTotal>2 と InjuriesTotal=3 についてフィルタし、BETWEEN フィルタは InjuriesTotal が 3 以上 5 以下のものをフィルタします。引数なしの DropData() はメタデータを削除しないので、この例では DropData(1)Opens in a new tab メソッドを使用しています。また、データのリストとロードを行う前に AddField()Opens in a new tab メソッドを呼び出す必要があることに注意してください。

#Include %IKPublic
DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData(1)
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 100 ID AS UniqueVal,Type,NarrativeFull,InjuriesTotal,InjuriesTotalFatal FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
   SET metaflds=$LB("InjuriesTotal","InjuriesTotalFatal")
AddMetaFields
  SET val=##class(%iKnow.Queries.MetadataAPI).AddField(domId,"InjuriesTotal",
                   $LB("=","<",">","BETWEEN"),$$$MDDTNUMBER)
  SET val=##class(%iKnow.Queries.MetadataAPI).AddField(domId,"InjuriesTotalFatal",
                   $LB("=","<",">","BETWEEN"),$$$MDDTNUMBER)
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds,metaflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
CountSources
   SET numsrc=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
ApplyFilter
  SET filt2=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,"InjuriesTotal",
                    ">",2)
  SET numSrcF2=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt2)
  WRITE "Of these ",numsrc," sources ",numSrcF2," had three or more injuries",!
  SET filt3=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,"InjuriesTotal",
                    "=",3)
  SET numSrcF3=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filt3)
  WRITE "Of these ",numsrc," sources ",numSrcF3," had three injuries",!
  SET filtb=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,"InjuriesTotal",
                    "BETWEEN","3;5")
  SET numSrcFb=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,filtb)
  WRITE "Of these ",numsrc," sources ",numSrcFb," had between 3 and 5 injuries",!

メタデータ・フィルタ演算子

それぞれのフィルタに 1 つ以上の等値演算子を割り当てます。フィルタを文字列値とマッチングする場合は、“=” 等値演算子を使用します。フィルタを数値とマッチングする場合は、“=”、“<”、“<=”、“>”、“>=” のうち 1 つ以上の演算子を使用できます。等値演算子は常に、リスト構造の引用符付きの文字列要素として指定します。等値演算子は 1 つの値に対してマッチングされます。詳細は、以下の例を参照してください。

  SET filt=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,metafldname,"=",today)

BETWEEN 演算子は、$$$MDVALSEPARATOR (セミコロン文字) で区切られる値のペアを含むパラメータ文字列に対してマッチングされます。詳細は、以下の例を参照してください。

  SET filt=##class(%iKnow.Filters.SimpleMetadataFilter).%New(domId,metafldname,
                   "BETWEEN","yesterday;tomorrow")

SQL クエリによるフィルタ

%iKnow.Filters.SqlFilterOpens in a new tab クラスでは、SQL クエリの結果に基づいて SQL ソースを選択できます。このクエリでは、以下のフィールドのいずれかを選択できます。

  • SourceId : 選択されたソースの (内部の) ソース ID

  • ExternalId : 選択されたソースの完全な外部 ID

  • IdField および GroupField : ドメインにソースを追加する際に識別子として共に使用される 2 つの列。つまり、ローカル参照 (IdField) およびグループ名 (GroupField)。%iKnow.Source.SQL.Lister も参照してください。

これらの結果列名では、大文字と小文字が区別されることに注意してください。

例えば、以下のフィルタでは、6 番目に取得されたソースの SourceId が選択されます (この場合、SourceId 45)。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
  IF ##class(%iKnow.Configuration).Exists("myconfig") {
         SET cfg=##class(%iKnow.Configuration).Open("myconfig") }
  ELSE { SET cfg=##class(%iKnow.Configuration).%New("myconfig",0,$LISTBUILD("en"),"",1)
         DO cfg.%Save() }
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
UseListerAndLoader
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
   DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.result,domId,1,50)
FilterSources
  SET filter=##class(%iKnow.Filters.SqlFilter).%New(domId,
       "SELECT '"_$LIST(result(6),1)_"' AS SourceId")
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(.fresult,domId,0,0,filter)
  WRITE !,"Filtered results:",!
  SET j=1
  WHILE $DATA(fresult(j)) {
    WRITE $LISTTOSTRING(fresult(j)),!
    SET j=j+1 }

以下のフィルタでは、ExternalId でソースが選択されます。

  SET filter=##class(%iKnow.Filters.SqlFilter).%New(domId,
          "SELECT '"_$LIST(result(1),2)_"' AS ExternalId")
  DO ##class(%iKnow.Queries.SourceAPI).GetByDomain(domId,0,0,filter)
  ZWRITE result  

フィルタ・モード

FilterMode 引数は、フィルタ適用後に実行する必要がある統計上の再処理を指定します。再処理を実行しない場合、フィルタは適用されますが、頻度および分散統計はフィルタ処理前に項目について計算された値になり、並べ替え順序は前と同じになります。使用できるフィルタ・モードを以下に示します。

FilterMode 整数コード フィルタ処理 頻度の再計算 分散の再計算 結果を再度並べ替え
$$$FILTERONLY 1 あり なし なし なし
$$$FILTERFREQ 3 あり あり なし なし
$$$FILTERSPREAD 5 あり なし あり なし
$$$FILTERALL 7 あり あり あり なし
$$$FILTERFREQANDSORT 11 あり あり なし あり
$$$FILTERSPREADANDSORT 13 あり なし あり あり
$$$FILTERALLANDSORT 15 あり あり あり あり

既定値は $$$FILTERONLY です。

$$$ マクロの使用方法は、“iKnow の実装” の章の "定数" を参照してください。

GroupFilter の使用による複数フィルタの組み合わせ

iKnow では GroupFilter クラスを提供することで、ロジックを指定して、他のフィルタの結果を組み合わせることを可能にしています。最初は、定義されたロジックを提供する GroupFilter インスタンスを作成して、次に AddSubFilter()Opens in a new tab メソッドを使用して、GroupFilter ロジックに従って組み合わせるサブフィルタ・オブジェクトを 1 つ以上割り当てます。このようにして複数の既存フィルタを組み合わせて、iKnow クエリに提供するソースを選択できます。

最も簡単な GroupFilter ロジックでは、単一フィルタの反転が返ります。以下の例では、RandFilt がソースの 33% を選択します。GroupFilter は Negated ブーリアン演算子により AND ロジックを定義します。単一フィルタに適用されると、このロジックはフィルタで選択されないソースをすべて返します。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineARandomFilter
  SET randfilt=##class(%iKnow.Filters.RandomFilter).%New(domId,.33)
SampledSourceQueries
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,randfilt)
  WRITE "From ",numSrcD," sources randfilt sampled ",numSrcFD,!
GroupFilter
    SET grpfilt=##class(%iKnow.Filters.GroupFilter).%New(domId,"AND",1)
    DO grpfilt.AddSubFilter(randfilt)
  SET numSrcGrp=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,grpfilt)
  WRITE "From ",numSrcD," sources grpfilt sampled ",numSrcGrp

以下の例では、GroupFilter を使用して、2 つの他のフィルタの結果を組み合わせます (この場合、共にランダム・フィルタ)。GroupFilter ロジックは AND、かつ Negated=0 であるため、GroupFilter の結果は RandomFilter の両セットにあるソースとなります。これらのフィルタの結果はランダムであるため、GroupFilter AND の結果の数は本例の実行毎に異なる可能性があります。

DomainCreateOrOpen
  SET dname="mydomain"
  IF (##class(%iKnow.Domain).Exists(dname))
      { SET domoref=##class(%iKnow.Domain).Open(dname)
        GOTO DeleteOldData }
  ELSE { SET domoref=##class(%iKnow.Domain).%New(dname)
         DO domoref.%Save()
         GOTO SetEnvironment }
DeleteOldData
  SET stat=domoref.DropData()
  IF stat { GOTO SetEnvironment }
  ELSE    { WRITE "DropData error ",$System.Status.DisplayError(stat)
            QUIT}
SetEnvironment
  SET domId=domoref.Id
QueryBuild
   SET myquery="SELECT TOP 50 ID AS UniqueVal,Type,NarrativeFull FROM Aviation.Event"
   SET idfld="UniqueVal"
   SET grpfld="Type"
   SET dataflds=$LB("NarrativeFull")
ListerAndLoader
  SET domId=domoref.Id
  SET flister=##class(%iKnow.Source.SQL.Lister).%New(domId)
  SET myloader=##class(%iKnow.Source.Loader).%New(domId)
  SET stat=flister.AddListToBatch(myquery,idfld,grpfld,dataflds)
      IF stat '= 1 {WRITE "The lister failed: ",$System.Status.DisplayError(stat) QUIT }
  SET stat=myloader.ProcessBatch()
      IF stat '= 1 {WRITE "The loader failed: ",$System.Status.DisplayError(stat) QUIT }
DefineTwoRandomFilters
  SET randfilt1=##class(%iKnow.Filters.RandomFilter).%New(domId,.33)
  SET randfilt2=##class(%iKnow.Filters.RandomFilter).%New(domId,.25)
  SET numSrcD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId)
  WRITE "The ",dname," domain contains ",numSrcD," sources",!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,randfilt1)
  WRITE "From ",numSrcD," sources randfilt1 sampled ",numSrcFD,!
  SET numSrcFD=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,randfilt2)
  WRITE "From ",numSrcD," sources randfilt2 sampled ",numSrcFD,!
GroupFilter
    SET grpfilt=##class(%iKnow.Filters.GroupFilter).%New(domId,"AND",0)
    DO grpfilt.AddSubFilter(randfilt1)
    DO grpfilt.AddSubFilter(randfilt2)
  SET numSrcGrp=##class(%iKnow.Queries.SourceAPI).GetCountByDomain(domId,grpfilt)
  WRITE "From ",numSrcD," sources grpfilt sampled ",numSrcGrp

それぞれの GroupFilter に AND ($$$GROUPFILTERAND) または OR ($$$GROUPFILTEROR) 論理演算子を割り当てます。したがって、AND ロジックと OR ロジックの両方を使用する複合フィルタを作成するには、AND ロジックを使用した GroupFilter と OR ロジックを使用した GroupFilter を作成する必要があります。

以下の例は、ブーリアン式 "(filter1 AND !(filter2 OR filter3))" に対応しています。

#Include %IKPublic
   SET domoref=##class(%iKnow.Domain).%New("MyDomain")
   DO domoref.%Save()
   SET domId=domoref.Id
   /* . . . */
Create3Filters
    /* . . . */
GroupFilters
  SET group1=##class(%iKnow.Filters.GroupFilter).%New(domId,$$$GROUPFILTERAND,0)
  SET group2=##class(iKnow.Filters.GroupFilter).%New(domId,$$$GROUPFILTEROR,1)
  DO group1.AddSubFilter(filter1)
  DO group2.AddSubFilter(filter2)
  DO group2.AddSubFilter(filter3)
  DO group1.AddSubFilter(group2)
FeedbackOpens in a new tab