Neo4j Cypher NULL值和降序排序

时间:2017-09-08 14:36:03

标签: neo4j cypher

我为所有实体提交了审核:

createDate
updateDate

我始终在实体创建期间初始化createDate,但updateDate可以包含NULL,直到第一次更新。

我必须在这些字段上实现排序功能。

使用createDate一切正常,但updateDate我遇到了问题。

如果在降序排序期间updateDate中有一组混合的NULL和Dates,我首先得到NULL,这不是我在这里期待的东西。

据我所知,根据Neo4j文档,这是一种期待的行为 - When sorting the result set, null will always come at the end of the result set for ascending sorting, and first when doing descending sort. 但我现在还不知道如何从用户角度实现正确的排序,用户将看到最新的排序列表顶部的更新文档。前段时间我甚至为此功能创建了GitHub问题https://github.com/opencypher/openCypher/issues/238

我可以在这里看到一个解决方法 - 在实体创建过程中同时填充updateDatecreateDate,但我真的很讨厌这个解决方案。

是否还有其他解决方案才能正确执行此任务?

3 个答案:

答案 0 :(得分:1)

您可以尝试使用coalesce() function。它将返回传递给它的表达式列表中的第一个非null值。

MATCH (n:Node)
RETURN n
ORDER BY coalesce(n.updateDate, 0) DESC

修改

来自评论:

  

在数据库级别上它是这样的:“updateDate”:   “2017-09-07T22:27:11.012Z”。在SDN4级别上它是Java -   java.util.Date类型

在这种情况下,您可以将0更改为表示开始时间常量的日期(例如“1970-01-01T00:00:00.000Z”)。

MATCH (n:Node)
RETURN n
ORDER BY coalesce(n.updateDate, "1970-01-01T00:00:00.000Z") DESC

答案 1 :(得分:1)

当updateDate为空时,我只使用createDate作为updateDate:

MATCH (n:Node)
RETURN n
ORDER BY coalesce(n.updateDate, n.createDate) DESC

答案 2 :(得分:1)

您可能需要考虑将ISO 8601时间戳字符串存储为(毫秒)整数。这可能会使涉及日期时间操作的大多数查询更有效(甚至可能),并且与等效字符串相比也会占用更少的数据库空间。

进行转换的一种方法是使用APOC函数apoc.date.parse。例如,这会将2017-09-07T22:27:11.012Z转换为整数(以毫秒为单位):

apoc.date.parse('2017-09-07T22:27:11.012Z', 'ms', "yyyy-MM-dd'T'HH:mm:ss.SSSX")

通过对数据模型的此更改,您还可以在节点创建时将updateDate初始化为0。这样可以避免使用COALESCE(n.updateDate, 0)进行排序(如@Bruno Peres所建议的那样),  并且0值将用作指示节点从未更新。  (但缺点是所有节点都有updateDate属性,即使是那些从未更新的属性。)