3

これはかなり単純なクエリのように思えますが、私はこれについて何時間も頭を悩ませてきました。以下のようなノード構造があります。

food-group
    jcr:content
        nuts -> type=almonds
        meat -> beef=true
        fruit -> type=apples,oranges,bananas

子ノードから収集する必要があるプロパティには、文字列、ブール値、および文字列配列の 3 種類があります。次のsql2クエリが機能し、それらのプロパティを取得すると思いますが、何らかの理由でエラーが発生します:

クエリ

SELECT 
    parent.* 
FROM 
    [cq:PageContent] AS parent 
INNER JOIN 
    [nt:base] as child ON ISCHILDNODE(parent) 
WHERE 
    ISDESCENDANTNODE(parent, [/content/grocerystore/food/])"

エラー:

Need to specify the selector name because the query contains more than one selector.

私は過去数日間これに携わってきたので、どんな助けも大歓迎です。

4

2 に答える 2

7

ISCHILDNODEJCR-SQL2 クエリで関数を使用できる場所は 2 つありますWHERE。句と結合条件です。残念ながら、それらは異なるパラメータを取ります。

ISCHILDNODEクエリは結合条件でを使用しようとしています。これには、子ノードのセレクター名と親ノードのセレクター名の 2 つのパラメーターが必要です。

あなたが欲しいと思うクエリは次のとおりです。

SELECT parent.* 
FROM [cq:PageContent] AS parent 
INNER JOIN [nt:base] as child ON ISCHILDNODE(child,parent) 
WHERE ISDESCENDANTNODE(parent, [/content/grocerystore/food/])

唯一の変更点は、ISCHILDNODE関数のパラメーターです。

残念ながら、エラー メッセージではこれがはっきりとわかりません。理由を理解するには、節ISCHILDNODEで使用されているの別の形式について知っておくと役立ちます。WHEREこのフォームには、子ノードを表すセレクターの名前と、親のリテラル パス (結果のノードが子になる) の2 つのパラメーターも必要です。この形式を使用する不自然なクエリを次に示します。

SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE(node,[/content/grocerystore])

クエリ結果には、ノードの子であるすべてのノードが含まれ/content/grocerystoreます。

ここで、クエリでセレクターが 1 つだけ定義されている場合 (たとえば、非結合)、ISCHILDNODE関数に渡すことができるセレクター名は 1 つだけです。厳密に言えば、セレクターは暗黙的に認識されているため、JCR-SQL2 ではパスのみを渡すことができます。以下は、前の不自然な例と意味的に同じクエリです。

SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE([/content/grocerystore])

これはISCHILDNODE単一のパラメーターを取る唯一の形式であり、これは CQ5 が期待していると私が考える形式だと思います。エラーは、クエリが複数のセレクターを定義しているため、セレクターを最初のパラメーターとして指定する必要があることを示しています。

もちろん、結合条件に表示される関数の形式を実際に使用しているため、これは非常に誤解を招く可能性があります。関数には子セレクター名と親セレクター名が必要であることを示すエラー メッセージの方が適切です。

于 2014-06-01T02:07:09.533 に答える
1

この例外は、複数のセレクター (この場合はand ) を持つ でgetNodes()メソッドを呼び出すとスローされます。このメソッドは、 を呼び出す場合にも使用されます。QueryResultparentchildfindResources()ResourceResolver

QueryResult#getRows()代わりに次のメソッドを使用してください。

Session session = resourceResolver.adaptTo(Session.class);
QueryManager queryManager = session.getWorkspace().getQueryManager();
Query query = queryManager.createQuery("...", Query.JCR_SQL2);
QueryResult result = query.execute();
// consider using result.getColumnNames() here
RowIterator rows = result.getRows();
while (rows.hasNext()) {
    Row row = rows.nextRow();
    // use row.getValue() or row.getValues()
}

いくつかのコメント:

  1. childへの最初のパラメーターとして追加する SQL クエリを修正する必要がありますISCHILDNODE(parent)
  2. SELECTを使用するのではなく、句で明示的にプロパティ リストを渡すparent.*ため、 を呼び出す必要はありませんresult.getColumnNames()
  3. クエリは非常に複雑で、それを呼び出す方法はさらに複雑です。Sling メソッドを使用foodして、リポジトリ内のスペースを反復処理してみませんか? ツリーを反復処理するのに最適なユースケースのようです。
    • SlingQueryプロジェクトにも興味があるかもしれません。
于 2014-05-31T20:32:00.287 に答える