Neo4j:找到所有可能的组合
Neo4j: Find all possible combinations
我目前正在努力解决有关组合学的问题。
对于原型,我想尝试 neo4j-ogm。
这是我目前设计的领域模型:
@NodeEntity
public class Operand {
@GraphId
private Long graphId;
}
@NodeEntity
public class Option extends Operand {
private Long id;
private String name;
@Relationship(type = "CONDITIONED_BY")
private List<Rule> rules = new ArrayList<>();
}
@NodeEntity
public class Operation extends Operand {
@Relationship(type = "COMPOSITION", direction = Relationship.INCOMING)
private Rule composition;
private Operation superOperation;
private Boolean not;
private List<Operand> operands = new ArrayList<>();
}
public class AndOperation extends Operation {
// Relationships named accordingly "AND"
}
public class OrOperation extends Operation {
// Relationships named accordingly "OR"
}
@NodeEntity
public class Rule {
@GraphId
private Long graphId;
@Relationship(type = "COMPOSITION")
private Operation composition;
@Relationship(type = "CONDITIONED_BY", direction = Relationship.INCOMING)
private Option option;
}
这是我的图表的一个片段:
表示类似于 (167079 ^ ...) & (167155 ^ ...)
是否可以在密码中形成查询,从而产生所有可能的组合?
167079, 167155
167079, 167092
...
我发现这个 resource 处理的是一个远距离相关的问题。
您认为这是 neo4j 的合适用例吗?
您是否建议对领域模型进行任何更改?
你有什么其他技术推荐吗?
编辑:
示例图只显示了我原始图的一小部分,我必须计算各种深度和各种封装操作的排列。
是的,我们可以通过在方程的每一边收集(两个集合)然后展开每个集合来得到这个。
假设传入两个集合作为参数:
UNWIND {first} as first
UNWIND {second} as second
RETURN first, second
这应该为您提供两个集合的元素之间的笛卡尔积。
编辑
如果知道您有多少个 AND 分支(例如 2 个),您可以这样形成查询:
MATCH (first)<-[:OR*0..]-()<-[:AND]-(root)-[:AND]->()-[:OR*0..]->(second)
WHERE id(root) = 168153
RETURN first, second
(编辑,匹配本身会在这里为你生成笛卡尔积)
至于您不知道有多少个 AND 分支的操作,我认为您无法仅使用 Cypher 使用这种方法来完成此操作,因为我不认为支持动态列。
您也许可以使用集合来完成此操作,但操作会很棘手。
在给定两个集合的情况下执行叉积的自定义过程在这种情况下会非常有用。如果您可以沿 AND 分支收集所有节点集合,则可以在其上 运行 REDUCE() ,对每个集合应用叉积过程。
至于具有更多操作的更复杂的树,我认为您无法通过 Cypher 做到这一点。我强烈推荐自定义过程,您将拥有更多控制权并能够使用条件逻辑、递归和方法调用。
我目前正在努力解决有关组合学的问题。
对于原型,我想尝试 neo4j-ogm。
这是我目前设计的领域模型:
@NodeEntity
public class Operand {
@GraphId
private Long graphId;
}
@NodeEntity
public class Option extends Operand {
private Long id;
private String name;
@Relationship(type = "CONDITIONED_BY")
private List<Rule> rules = new ArrayList<>();
}
@NodeEntity
public class Operation extends Operand {
@Relationship(type = "COMPOSITION", direction = Relationship.INCOMING)
private Rule composition;
private Operation superOperation;
private Boolean not;
private List<Operand> operands = new ArrayList<>();
}
public class AndOperation extends Operation {
// Relationships named accordingly "AND"
}
public class OrOperation extends Operation {
// Relationships named accordingly "OR"
}
@NodeEntity
public class Rule {
@GraphId
private Long graphId;
@Relationship(type = "COMPOSITION")
private Operation composition;
@Relationship(type = "CONDITIONED_BY", direction = Relationship.INCOMING)
private Option option;
}
这是我的图表的一个片段:
表示类似于 (167079 ^ ...) & (167155 ^ ...)
是否可以在密码中形成查询,从而产生所有可能的组合?
167079, 167155
167079, 167092
...
我发现这个 resource 处理的是一个远距离相关的问题。
您认为这是 neo4j 的合适用例吗?
您是否建议对领域模型进行任何更改?
你有什么其他技术推荐吗?
编辑:
示例图只显示了我原始图的一小部分,我必须计算各种深度和各种封装操作的排列。
是的,我们可以通过在方程的每一边收集(两个集合)然后展开每个集合来得到这个。
假设传入两个集合作为参数:
UNWIND {first} as first
UNWIND {second} as second
RETURN first, second
这应该为您提供两个集合的元素之间的笛卡尔积。
编辑
如果知道您有多少个 AND 分支(例如 2 个),您可以这样形成查询:
MATCH (first)<-[:OR*0..]-()<-[:AND]-(root)-[:AND]->()-[:OR*0..]->(second)
WHERE id(root) = 168153
RETURN first, second
(编辑,匹配本身会在这里为你生成笛卡尔积)
至于您不知道有多少个 AND 分支的操作,我认为您无法仅使用 Cypher 使用这种方法来完成此操作,因为我不认为支持动态列。
您也许可以使用集合来完成此操作,但操作会很棘手。
在给定两个集合的情况下执行叉积的自定义过程在这种情况下会非常有用。如果您可以沿 AND 分支收集所有节点集合,则可以在其上 运行 REDUCE() ,对每个集合应用叉积过程。
至于具有更多操作的更复杂的树,我认为您无法通过 Cypher 做到这一点。我强烈推荐自定义过程,您将拥有更多控制权并能够使用条件逻辑、递归和方法调用。