您可以在 JCR-SQL2 和 XPath 中执行此操作。
标准 JCR-SQL2
假设您有一个名为Person
withname
和nickname
字段的节点类型,那么在 JCR-SQL2 中实现接近所需结果的一种方法是:
SELECT p.name, p.nickname FROM Person AS p ORDER BY p.name ASC, p.nickname ASC
但是我们可以把这个查询写得更清楚一点,因为只有一个选择器(即一个“表”),我们可以省略可选的ASC
SELECT name, nickname FROM Person ORDER BY name, nickname
现在,严格来说,您从此查询中获得的结果将取决于实现,这是因为您在问题中描述了该nickname
字段如何为空,并且 JCR 2.0 规范没有指定排序如何处理NULL
值。例如,它们应该出现在非空值之前还是之后?实施可以选择。
还有一个棘手的问题。请注意,我假设Person
节点类型有一个name
字段,而不是假设您将人名存储在节点名称中。这是因为在 JCR-SQL2 中,您必须使用名为NODENAME
or的特殊函数来访问节点的名称NODELOCALNAME
。您可以直接在排序中使用它,但不幸的是,在标准 JCR-SQL2 中没有定义在查询结果中获取节点的名称。
因此,使用标准 JCR-SQL2 的以下查询将起作用:
SELECT nickname FROM Person ORDER BY NODELOCALNAME, nickname
但是您必须javax.jcr.Node
从结果中获取节点的名称,而不是结果集中的值之一。严格来说,这既不贵也不难;它只是改变了您的应用程序使用查询结果的方式。
ModeShape 中的 JCR-SQL2
一种 JCR 实现 ModeShape 扩展了标准 JCR-SQL2 语法,增加了许多附加功能。其中一个扩展是引入几个伪列,包括:
jcr:name
是节点名称的替代
jcr:path
是节点路径的替身
mode:localName
是节点名称的本地部分的替代
mode:depth
计算节点的深度
jcr:uuid
评估结果为javax.jcr.Node.getUUID()
因此,您可以jcr:name
在排序和 SELECT 子句中使用伪列:
SELECT jcr:name, nickname FROM Person ORDER BY jcr:name, nickname
这些选项在 ModeShape 3.x 中可用。但是社区目前正在开发 ModeShape 4.0(目前处于 Alpha 阶段),并且添加了一个扩展:您可以指定空值在排序中应该排在第一位还是排在最后。这是早期查询的一个变体,展示了如何使用它:
SELECT name, nickname FROM Person ORDER BY name NULLS FIRST, nickname NULLS FIRST
如果您的Person
节点类型定义确保该name
属性是强制性的(从不为空),则不需要在列排序上指定NULLS FIRST
(or NULLS LAST
) 。name
这是相同的查询,除了 withjcr:name
而不是name
:
SELECT jcr:name, nickname FROM Person ORDER BY jcr:name, nickname NULLS FIRST
请注意,我们不需要在列上指定NULLS FIRST
或,因为每个节点都有一个名称,因此永远不会为空。NULLS LAST
jcr:name
jcr:name
标准 JCR 1.0 XPath
如果您使用的 JCR 实现仍然支持 XPath(在技术上被指定为 JSR-170 或 JCR 1.0 的一部分,并且在 JSR-283 或 JCR 2.0 中已弃用),您还可以使用 XPath:
//element(*, Person) order by @name ascending, @nickname ascending
由于 JCR 1.0 确实定义了jcr:name
伪列,因此您实际上可以很容易地使用节点的名称:
//element(*, Person) order by @jcr:name ascending, @nickname ascending
还有一件事:ModeShape 3.x 或更高版本将用 JCR-SQL2、XPath 和 JCR-SQL 编写的查询解析为相同的抽象语法树,然后执行它们。因此,最后一个 JCR-SQL2 查询和最后一个 XPath 查询在 ModeShape 中的处理方式相同。