这似乎是一个相当简单的查询,但我已经在这个问题上敲了几个小时。我有一个类似于下面的节点结构:
food-group
jcr:content
nuts -> type=almonds
meat -> beef=true
fruit -> type=apples,oranges,bananas
我需要从子节点收集三种类型的属性:一个是字符串,布尔和字符串数组。我认为以下sql2查询将起作用并获取它们的属性,但无论出于何种原因我都会收到错误:
QUERY
SELECT parent.* FROM [cq:PageContent] AS parent INNER JOIN [nt:base] as child ON ISCHILDNODE(parent) WHERE ISDESCENDANTNODE(parent, [/content/grocerystore/food/])"
ERROR:
Need to specify the selector name because the query contains more than one selector.
任何帮助都会受到赞赏,因为我过去几天一直在这里。
答案 0 :(得分:6)
有两个地方可以在JCR-SQL2查询中使用ISCHILDNODE
函数:在WHERE
子句和连接条件中。不幸的是,它们采用了不同的参数。
您的查询正在尝试使用加入条件中的ISCHILDNODE
,这需要两个参数:子节点的选择器名称和父节点的选择器名称。 / p>
这是我认为你想要的查询:
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
子句中使用的形式是有帮助的。该表单还需要两个参数:表示子节点的选择器的名称,以及父节点的文字路径(生成的节点是子节点)。这是一个使用此表单的人为查询:
SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE(node,[/content/grocerystore])
查询结果将包含/content/grocerystore
节点的子节点的所有节点。
现在,如果查询只定义了一个选择器(例如,非连接),那么只有一个选择器名称可以传递给ISCHILDNODE
函数。严格地说,选择器是隐式已知的,因此JCR-SQL2允许您仅传入路径。这是一个在语义上与之前设想的示例相同的查询:
SELECT node.*
FROM [nt:base] AS node
WHERE ISCHILDNODE([/content/grocerystore])
这是唯一采用单个参数的ISCHILDNODE
形式,我认为这是我认为CQ5期望的形式:错误表明查询定义了多个选择器,因此选择器必须作为第一个参数提供。
当然,这是非常误导的,因为您实际上正在使用加入条件中出现的函数形式。更好的错误消息会说该函数需要子选择器名称和父选择器名称。
答案 1 :(得分:1)
如果您在具有多个选择器的getNodes()
上调用QueryResult
方法,则会抛出此异常(在您的情况下,parent
和child
)。如果您在findResources()
上调用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()
}
一些评论:
child
添加为ISCHILDNODE(parent)
的第一个参数。SELECT
子句中传递属性列表explicite,而不是使用parent.*
,因此您不必调用result.getColumnNames()
。food
空间?它似乎是迭代树的完美用例。