首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >"order by“基于表达式

"order by“基于表达式
EN

Stack Overflow用户
提问于 2014-04-01 16:19:31
回答 2查看 681关注 0票数 2

给出一个比较器:

代码语言:javascript
运行
复制
public int compareTo(Person p1, Person p2)
{
    String val1 = StringUtils.isEmpty(p1.nickName) ? p1.name : p1.nickName;
    String val2 = StringUtils.isBlank(p2.nickName) ? p2.name : p2.nickName;

    return val1.compareTo(val2);
}

我希望通过使用xpath查询的"order by“实现相同的结果(如果它超出了xpath的能力范围,则可以使用SQL2 )。有可能吗?

给定数据:

代码语言:javascript
运行
复制
No. |  Name    | Nickname |
 1  |  Adam    | Hornet   |
 2. |  Adam    |          |
 3. |  Jack    | Legend   |

排序后的数据:

代码语言:javascript
运行
复制
No. | name | nickname
2.  | Adam | 
1.  | Adam | Hornet
3.  | Jack | Legend
EN

回答 2

Stack Overflow用户

发布于 2014-04-01 22:04:52

在JCR-SQL2和XPath中都可以做到这一点。

标准JCR-SQL2

假设您有一个名为Person的节点类型,其中包含namenickname字段,那么在JCR-sql2中实现接近预期结果的一种方法是:

代码语言:javascript
运行
复制
SELECT p.name, p.nickname FROM Person AS p ORDER BY p.name ASC, p.nickname ASC

但是我们可以更简单地编写这个查询,因为只有一个选择器(即,一个“表”),并且我们可以省略可选的ASC

代码语言:javascript
运行
复制
SELECT name, nickname FROM Person ORDER BY name, nickname

现在,严格地说,从这个查询中获得的结果将取决于实现,这是因为您在问题中描述了nickname字段如何为NULL,而JCR2.0规范没有指定排序如何处理null值。例如,它们应该出现在非空值之前还是之后?实现可以选择。

还有另一个棘手的问题。注意,我假设Person节点类型有一个name字段,而不是假设您将person的名字存储在节点的名称中。这是因为在JCR-SQL2中,您必须使用名为NODENAMENODELOCALNAME的特殊函数来访问节点的名称。您可以直接在排序中使用它,但不幸的是,在查询结果中获取节点的名称没有在标准JCR-SQL2中定义。

因此,使用标准JCR-SQL2的以下查询将起作用:

代码语言:javascript
运行
复制
SELECT nickname FROM Person ORDER BY NODELOCALNAME, nickname

但是您必须从从结果中获得的javax.jcr.Node中获取节点的名称,而不是结果集中的一个值。严格地说,这既不昂贵也不困难;它只是改变了应用程序使用查询结果的方式。

ModeShape中的JCR-SQL2

一个JCR实现ModeShape使用许多additional features扩展了标准的JCR-SQL2语法。其中一个扩展是引入几个伪列,包括:

  • jcr:name是节点的替代name
  • jcr:path是节点的path
  • mode:localName是节点的本地部分的替代name
  • mode:depth求值为node
  • jcr:uuid的深度求值为javax.jcr.Node.getUUID()

的结果

因此,您可以在排序和SELECT子句中使用jcr:name伪列:

代码语言:javascript
运行
复制
SELECT jcr:name, nickname FROM Person ORDER BY jcr:name, nickname

这些选项在ModeShape 3.x中可用。但是社区目前正在开发ModeShape 4.0 (目前是Alpha4.0),并且添加了另一个扩展:您可以指定是否在排序中使用nulls should come first or last。下面是前面查询的一个变体,展示了如何使用它:

代码语言:javascript
运行
复制
SELECT name, nickname FROM Person ORDER BY name NULLS FIRST, nickname NULLS FIRST

如果您的Person节点类型定义确保name属性是强制的(从不为null),则不需要在name列排序上指定NULLS FIRST (或NULLS LAST)。

下面是相同的查询,只是使用了jcr:name而不是name

代码语言:javascript
运行
复制
SELECT jcr:name, nickname FROM Person ORDER BY jcr:name, nickname NULLS FIRST

注意,我们不需要在jcr:name列上指定NULLS FIRSTNULLS LAST,因为每个节点都有一个名称,因此jcr:name永远不会为null。

标准JCR1.0 XPath

如果您使用的JCR实现仍然支持XPath (从技术上讲,它是JSR-170或JCR1.0的一部分,在JSR-283或JCR2.0中已被弃用),则还可以使用XPath:

代码语言:javascript
运行
复制
//element(*, Person) order by @name ascending, @nickname ascending

由于JCR1.0确实定义了jcr:name伪列,因此实际上可以很容易地使用节点的名称:

代码语言:javascript
运行
复制
//element(*, Person) order by @jcr:name ascending, @nickname ascending

还有一件事:SQL3.x或更高版本将用ModeShape -SQL2、XPath和JCR-SQL语言编写的查询解析到相同的抽象语法树中,然后执行它们。因此,最后一个JCR-SQL2查询和最后一个XPath查询在ModeShape中的处理方式是相同的。

票数 0
EN

Stack Overflow用户

发布于 2014-04-01 22:41:10

下面是你如何在你的比较器中使用任意代码来做这件事的草图。获取从执行普通查询获得的NodeIterator

代码语言:javascript
运行
复制
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.query.NodeIterator;
import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

. . .

Query query = queryManager.createQuery( /* query without any ordering specs */ );
QueryResult queryResult = query.execute();
NodeIterator nodeIterator = queryResult.getNodes();

并将其传递给执行排序并返回另一个NodeIterator的方法

代码语言:javascript
运行
复制
NodeIterator sortedNodes = sortMyWay(nodeIterator);

. . .

private NodeIterator sortMyWay(NodeIterator input) {
    ArrayList<Node> results = new ArrayList<Node>();
    while (input.hasNext()) {
        results.add(input.nextNode());
    }
    Collections.sort(results, new Comparator<Node>(){
        @Override
        public int compare(Node node1, Node node2) {
            String nickName1 = (node1.hasProperty("nickName") ? node1.getProperty("nickName").getString() : "");
            String nickName2 = (node2.hasProperty("nickName") ? node2.getProperty("nickName").getString() : "");
            return nickName1.compareTo(nickName2);
        }
    });
    return new NodeIteratorAdapter(results);
}

像往常一样从sortedNodes.nextNode()检索结果。

根据需要在上述方法中添加异常处理,并根据需要在name属性中添加默认值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22780347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档