Neo4j Cypher多个WITH关键字

3
我有一个如下的Neo4j Cypher查询:
MATCH (parentD:Decision)-[:CONTAINS]->(childD:Decision) 
WHERE id(parentD) = {parentDecisionId} 
WITH childD, parentD 
OPTIONAL MATCH (parentD)<-[:DEFINED_BY]-(c:Criterion)<-[:VOTED_ON]-(vg:VoteGroup)-[:VOTED_FOR]->(childD) 
OPTIONAL MATCH (parentD)<-[:DEFINED_BY]-(ch:Characteristic)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(childD) 
WITH childD, {criterion: c,  weight: vg.avgVotesWeight} AS weightedCriterion, {characteristic: ch,  value: v.value} AS valuedCharacteristic 
RETURN childD AS decision, collect(weightedCriterion) AS weightedCriteria, collect(valuedCharacteristic) AS valuedCharacteristics

在我的SDN 4项目中,我希望能够检索到一个List<DecisionMatrix>列表。
@QueryResult
public class DecisionMatrix {

    private Decision decision;

    private List<WeightedCriterion> weightedCriteria;

    private List<ValuedCharacteristic> valuedCharacteristics;

}

@QueryResult
public class WeightedCriterion {

    private Criterion criterion;

    private Double weight;

}

@QueryResult
public class ValuedCharacteristic {

    private Characteristic characteristic;

    private Object value;
}

现在,此查询返回一个正确的标准列表,但是特征元素为空的列表是错误的。

例如,我没有任何符合此查询条件的特征,但结果中我可以看到以下结构,其中有两条记录:

RDBMS : [{criterion=Node[161], weight=4.333333333333333}, {criterion=Node[160], weight=2.1666666666666665}] : [{characteristic=null, value=null}, {characteristic=null, value=null}]

NoSQL : [{criterion=Node[160], weight=4.333333333333333}, {criterion=Node[161], weight=2.5}, {criterion=Node[162], weight=4.2}] : [{characteristic=null, value=null}, {characteristic=null, value=null}, {characteristic=null, value=null}]

结果包含了正确的关系型数据库(RDBMS)的标准(2个标准),以及非关系型数据库(NoSQL)的标准(3个标准),但是特征集合却错误了。我希望这两个记录都有一个空的特征列表(0个元素),因为这些节点没有相关的特征。但是在第一个记录中,我有两个空特征(与标准列表长度相同),在第二个记录中有三个空特征。
我做错了什么,如何解决?
1个回答

1
这是明确为值创建映射的结果:
... {characteristic: ch,  value: v.value} AS valuedCharacteristic ...

这将创建一个地图,并相应地设置值,这些值恰好为null,因为OPTIONAL MATCH无法匹配模式。将null值添加到地图中没有任何问题,而且没有任何东西本质上将地图的存在与其属性值之一(甚至全部)是null还是not null联系在一起。
对于Neo4j 3.1及更高版本,解决此问题并确保列表在没有特征时保持为空的最简单方法是完全跳过OPTIONAL MATCH,改用pattern comprehension。既然我们已经在做Criterion和VoteGroup方面的其他OPTIONAL MATCH,那么我们也可以这样做。
MATCH (parentD:Decision)-[:CONTAINS]->(childD:Decision) 
WHERE id(parentD) = {parentDecisionId} 
RETURN childD AS decision,
[ (parentD)<-[:DEFINED_BY]-(c:Criterion)<-[:VOTED_ON]-(vg:VoteGroup)-[:VOTED_FOR]->(childD) 
  | {criterion: c,  weight: vg.avgVotesWeight} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch:Characteristic)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(childD) 
  | {characteristic: ch,  value: v.value} ] AS valuedCharacteristics

如果您的模式推导中的模式不存在,则结果列表将为空。
对于Neo4j 3.0及以下版本,您可能需要坚持使用原始查询,但使用CASE语句在相应变量为null时有条件地发出null而不是您的valuedCharacteristic(和weightedCriterion)映射。使用此选项的代码片段如下:
... CASE WHEN ch IS NULL THEN null ELSE {characteristic: ch,  value: v.value} END AS valuedCharacteristic

非常感谢!这正是我所需要的。我使用的是Neo4j 3.1。 - alexanoid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接