让我们从一个示例数据集开始。有 2 个节点和 2 个关系,它们之间的关系类型不同。节点和关系都有属性。不要过多关注语义,这是源自我无法直接在此处展示的用例。
create (a:AlphaNode {name: "Alice"} )
create (b:BetaNode {name: "Bob"} )
create (a)-[:HAS {really: false} ]->(b)
create (a)-[:NEEDS {timespan: 42} ]->(b)
现在,我想按照以下方式运行查询:
match (a:AlphaNode)-[r:HAS|NEEDS]->(b:BetaNode)
// where etc ... (not important in the example)
return a, r, b
这将返回 2 个结果集,其中节点是相同的,只有
r
表示的关系在结果集之间会有所不同。
我使用 Neo4jClient 的 C# 代码应如下所示:
client.Cypher
.Match("(a:AlphaNode)-[r:HAS|NEEDS]->(b:BetaNode)")
.ReturnDistinct((a, r, b) => new
{
A = a.As<AlphaNode>(),
R = r.As<SomeRelationship>(),
B = b.As<BetaNode>()
})
// .ResultAsync etc. (not important, here)
;
现在,我遇到了
SomeRelationship
的问题。当然,我可以将其设为 POCO/DTO,但这样我就无法访问关系类型(HAS
或 NEEDS
)。我在文档中找不到好的提示或示例,我发现的只是对 Relationship
、RelationshipInstance
、RelationshipReference
类的提示(它们具有关系类型,但这不是从数据库,而是通过类继承来固定),但我不能真正让它们(或者更准确地说是它们的后代)像这样工作(即使对于单个关系,但动态才是真正的点,在这里)。
有没有一种方法可以使用动态关系 POCO 比使用一些奇怪的继承更干净地完成此操作,这些继承主要是为了用无参数的构造函数替换构造函数?我认为这些课程的意图与我的预期有点不同。不要误会我的意思,我很想继承一个关系型基类,但是基类必须从响应中提供关系类型,并且首先要有一个无参数构造函数。
我会给出一个答案,因为我遇到了与你类似的问题。根据您的需要,我有几个解决方案。
此方法要求您修改返回的匿名对象以容纳
Dictionary<string, string>
中的所有关系属性以及 string
中的关系类型。
client.Cypher
.Match("(a:AlphaNode)-[r:HAS|NEEDS]->(b:BetaNode)")
.ReturnDistinct((a, r, b) => new
{
A = a.As<AlphaNode>(),
RelationshipProperties = r.CollectAs<Dictionary<string, string>>(),
RelationshipType = r.Type(),
B = b.As<BetaNode>()
}).ResultsAsync;
对于您的情况来说可能有点过分了,但对于我的用例来说这是必要的。您可以使用以下查询将整个路径(节点和关系)作为 JSON 字符串返回。然后,您可以根据需要将其序列化到您的模型中。
client.Cypher
.Match("path = (a:AlphaNode)-[r:HAS|NEEDS]->(b:BetaNode)")
.Return<string>("path")
.ResultsAsync;