Query Builder 用のカスタム述語エバリュエーターの実装

ここでは、カスタム述語エバリュエーターを実装して、Query Builder を拡張する方法について説明します。

概要

Query Builder を使用すると、コンテンツリポジトリへのクエリを簡単に実行できます。AEMには、データ処理に役立つ述語評価演算子のセットが付属しています。

しかし、カスタム述語エバリュエーターを実装することによって、複雑さを軽減し、セマンティックを向上させて、クエリを単純化することができます。

他にも、カスタム述語では、以下のような XPath では直接実行できないことも実行できます。

  • 何らかのサービスの何らかのデータの検索
  • 計算に基づくカスタムフィルタリング
メモ

カスタム述語を実装する際は、パフォーマンスの問題を考慮する必要があります。

メモ

クエリの例については、Query Builder の節を参照してください。

GitHub のコード

このページのコードは GitHub にあります

述語エバリュエーターの詳細

述語エバリュエーターは、クエリの制約を定義する特定の述語を評価します。

特定の JCR クエリに対する高度な検索制約("width > 200" など)を、実際のコンテンツモデルに合わせてマッピングします(例:metadata/@width > 200)。ノードを手動でフィルタリングして、制約をチェックすることもできます。

メモ

PredicateEvaluator および com.day.cq.search パッケージについて詳しくは、Java のドキュメントを参照してください。

レプリケーションメタデータ用のカスタム述語エバリュエーターの実装

例として、レプリケーション・メタデータに基づくデータを支援するカスタム述語評価基準を作成する方法を説明します。

  • cq:lastReplicated:最終レプリケーションアクションの日付を格納

  • cq:lastReplicatedBy:最終レプリケーションアクションを呼び出したユーザーの ID を格納

  • cq:lastReplicationAction:最終レプリケーションアクション(アクティベート、アクティベート解除など)を格納

デフォルトの述語エバリュエーターを使用したレプリケーションメタデータのクエリ

次のクエリは、adminが年の初めからアクティブ化した/contentブランチのノードのリストを取得します。

path=/content

1_property=cq:lastReplicatedBy
1_property.value=admin

2_property=cq:lastReplicationAction
2_property.value=Activate

daterange.property=cq:lastReplicated
daterange.lowerBound=2013-01-01T00:00:00.000+01:00
daterange.lowerOperation=>=

このクエリは有効ですが、解読しにくく、3 つのレプリケーションプロパティ間の関係が一目ではわかりません。カスタム述語評価基準を実装すると、このクエリの複雑さが軽減され、セマンティックが向上します。

目的

ReplicationPredicateEvaluator の目的は、以下のような構文を使用して上記のクエリをサポートすることです。

path=/content

replic.by=admin
replic.since=2013-01-01T00:00:00.000+01:00
replic.action=Activate

レプリケーションメタデータ述語をカスタム述語評価子でグループ化すると、意味のあるクエリを作成するのに役立ちます。

Maven 依存関係の更新

メモ

Maven を使用した新しい AEM プロジェクトの設定については、Apache Maven を使用した AEM プロジェクトの構築方法で説明されています。

まず、プロジェクトの Maven 依存関係を更新する必要があります。PredicateEvaluatorcq-search アーティファクトの一部なので、Maven の pom ファイルに追加する必要があります。

メモ

cq-search依存関係の範囲はprovidedに設定されます。これは、cq-searchOSGiコンテナによって提供されるからです。

pom.xml

次のスニペットは、unified diff形式の違いを示しています

@@ -120,6 +120,12 @@
             <scope>provided</scope>
         <dependency>
+            <groupid>com.day.cq</groupid>
+            <artifactid>cq-search</artifactid>
+            <version>5.6.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupid>junit</groupid>
             <artifactid>junit</artifactid>
             <version>3.8.1</version></dependency>

aem-search-custom-predicate-evaluator- pom.xml

ReplicationPredicateEvaluator の作成

cq-searchプロジェクトにはAbstractPredicateEvaluator抽象クラスが含まれています。 これは、独自のカスタム述語評価演算子(PredicateEvaluatorを実装するためのいくつかの手順で拡張できます)。

メモ

次の手順では、データをフィルタリングする Xpath 式を作成する方法について説明します。もう1つの方法は、行単位でデータを選択するincludesメソッドを実装することです。 詳しくは、Java のドキュメントを参照してください。

  1. com.day.cq.search.eval.AbstractPredicateEvaluator を拡張する新しい Java クラスを作成します。

  2. 次のように@Componentをクラスに注釈を付けます。

    src/main/java/com/adobe/aem/docs/search/ReplicationPredicateEvaluator.java

    次のスニペットは、unified diff形式の違いを示しています

@@ -19,8 +19,11 @@
  */
 package com.adobe.aem.docs.search;
+import org.apache.felix.scr.annotations.Component;
+import com.day.cq.search.eval.AbstractPredicateEvaluator;
+@Component(metatype = false, factory = "com.day.cq.search.eval.PredicateEvaluator/repli")
 public class ReplicationPredicateEvaluator extends AbstractPredicateEvaluator {

  }

aem-search-custom-predicate-evaluator- src/main/java/com/adobe/aem/docs/search/ReplicationPredicateEvaluator.java

メモ

factoryは、com.day.cq.search.eval.PredicateEvaluator/で始まり、カスタムPredicateEvaluatorの名前で終わる一意の文字列である必要があります。

メモ

PredicateEvaluator の名前は述語名で、クエリを組み立てる際に使用されます。

  1. オーバーライド:

    public String getXPathExpression(Predicate predicate, EvaluationContext context)
    

    オーバーライドメソッドでは、引数に指定された Xpath に基づいて Predicate 式を組み立てます。

レプリケーションメタデータ用のカスタム述語エバリュエーターの例

この PredicateEvaluator の完全な実装は、次のクラスのようになります。

src/main/java/com/adobe/aem/docs/search/ReplicationPredicateEvaluator.java

/*
 * #%L
 * aem-docs-custom-predicate-evaluator
 * %%
 * Copyright (C) 2013 Adobe Research
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package com.adobe.aem.docs.search;

import org.apache.felix.scr.annotations.Component;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

 
import com.day.cq.search.Predicate;

import com.day.cq.search.eval.AbstractPredicateEvaluator;

import com.day.cq.search.eval.EvaluationContext;

 
@Component(metatype = false, factory = "com.day.cq.search.eval.PredicateEvaluator/repli")

public class ReplicationPredicateEvaluator extends AbstractPredicateEvaluator {

    static final String PE_NAME = "replic";

    static final String PN_LAST_REPLICATED_BY = "cq:lastReplicatedBy";

    static final String PN_LAST_REPLICATED = "cq:lastReplicated";

    static final String PN_LAST_REPLICATED_ACTION = "cq:lastReplicationAction";

    static final String PREDICATE_BY = "by";

    static final String PREDICATE_SINCE = "since";

    static final String PREDICATE_SINCE_OP = " >= ";

    static final String PREDICATE_ACTION = "action";
 

    Logger log = LoggerFactory.getLogger(getClass());

    /**
     * Returns a XPath expression filtering by replication metadata.
     *
     * @see com.day.cq.search.eval.AbstractPredicateEvaluator#getXPathExpression(com.day.cq.search.Predicate,
     *      com.day.cq.search.eval.EvaluationContext)
     */

    @Override

    public String getXPathExpression(Predicate predicate,

            EvaluationContext context) {

        log.debug("predicate {}", predicate);


        String date = predicate.get(PREDICATE_SINCE);

        String user = predicate.get(PREDICATE_BY);

        String action = predicate.get(PREDICATE_ACTION);


        StringBuilder sb = new StringBuilder();


        if (date != null) {

            sb.append(PN_LAST_REPLICATED).append(PREDICATE_SINCE_OP);

            sb.append("xs:dateTime('").append(date).append("')");

        }

        if (user != null) {

            addAndOperator(sb);

            sb.append(PN_LAST_REPLICATED_BY);

            sb.append("='").append(user).append("'");

        }

        if (action != null) {

            addAndOperator(sb);

            sb.append(PN_LAST_REPLICATED_ACTION);

            sb.append("='").append(action).append("'");

        }

        String xpath = sb.toString();

        log.debug("xpath **{}**", xpath);

        return xpath;

    }

    /**
     * Add an and operator if the builder is not empty.
     *
     * @param sb a {@link StringBuilder} containing the query under construction
     */

    private void addAndOperator(StringBuilder sb) {

        if (sb.length() != 0) {

            sb.append(" and ");

        }

    }

}

aem-search-custom-predicate-evaluator - src/main/java/com/adobe/aem/docs/search/ReplicationPredicateEvaluator.java

このページ

Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now