为 return 添加临时 属性 到 Neo4j Cypher 中的节点
Add temporary property to node in Neo4j Cypher for return
我正在使用 Neo4j .Net 客户端与 Neo4j 数据库进行交互。
我在尝试将相关节点映射到嵌套 classes 时经常遇到这个问题:
例如映射
(:Foo)-[:FOOBAR]->(:Bar)
到表格
public class Foo {
public string FooPropOne { get; set; }
public string FooPropTwo { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar {
public string BarPropOne { get; set; }
public string BarPropTwo { get; set; }
}
为了获得反序列化的正确输出,我必须像这样编写查询:
Foo foo = WebApiConfig.GraphClient.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("@{
FooPropOne: f.FooPropOne,
FooPropTwo: f.FooPropTwo,
Bars: collect(b)
} AS Result")
.Return<Foo>("Result")
.SingleOrDefault();
在某种程度上这很好,并且工作得很好,但是随着 Foo class 具有的属性越多,它变得非常笨重。
我想知道我是否可以在 "With" 语句中做一些事情来在返回节点时添加一个临时的 属性(在上面的例子中 "Bars"),那确实不需要我在父节点上写每个 属性?
类似于
.With("f.Bars = collect(b)")
.Return<Foo>("f")
这实际上不会影响存储在数据库中的数据吗?
在此先感谢您的回复!
我不知道有什么方法可以像你想要的那样添加临时 属性,就个人而言 - 我会采用两种方法中的一种,而决定实际上取决于你喜欢做什么。
选项 1
选择属性版本
var foo = client.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("f, collect(b) as bars")
.Return((f, bars) => new Foo
{
FooPropOne = f.As<Foo>().FooPropOne,
FooPropTwo = f.As<Foo>().FooPropTwo,
Bars = Return.As<List<Bar>>("bars")
}).Results.SingleOrDefault();
此版本允许您对带出的对象进行类型安全处理,在具有大量属性的 class 上确实限制了输入错误的可能性。这将使您返回Foo
实例,所以不需要做任何其他处理。
选项 2
post-加工所需版本的一点点
var notQuiteFoo = client.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("f, collect(b) as bars")
.Return((f, bars) => new
{
Foo = f.As<Foo>(),
Bars = bars.As<List<Bar>>()
}).Results;
这节省了输入属性的时间,因此 class 大大节省了时间,还意味着如果您添加额外的属性,您无需记住更新查询。 但是你确实需要做一些post查询处理,比如:
IEnumerable<Foo> foos = notQuiteFoo.Results.Select(r => {r.Foo.Bars = r.Bars; return r.Foo;});
就个人而言 - 我喜欢 选项 2,因为它出现错别字的可能性较小,但我很欣赏这两者都不是您所追求的。
我正在使用 Neo4j .Net 客户端与 Neo4j 数据库进行交互。
我在尝试将相关节点映射到嵌套 classes 时经常遇到这个问题:
例如映射
(:Foo)-[:FOOBAR]->(:Bar)
到表格
public class Foo {
public string FooPropOne { get; set; }
public string FooPropTwo { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar {
public string BarPropOne { get; set; }
public string BarPropTwo { get; set; }
}
为了获得反序列化的正确输出,我必须像这样编写查询:
Foo foo = WebApiConfig.GraphClient.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("@{
FooPropOne: f.FooPropOne,
FooPropTwo: f.FooPropTwo,
Bars: collect(b)
} AS Result")
.Return<Foo>("Result")
.SingleOrDefault();
在某种程度上这很好,并且工作得很好,但是随着 Foo class 具有的属性越多,它变得非常笨重。
我想知道我是否可以在 "With" 语句中做一些事情来在返回节点时添加一个临时的 属性(在上面的例子中 "Bars"),那确实不需要我在父节点上写每个 属性?
类似于
.With("f.Bars = collect(b)")
.Return<Foo>("f")
这实际上不会影响存储在数据库中的数据吗?
在此先感谢您的回复!
我不知道有什么方法可以像你想要的那样添加临时 属性,就个人而言 - 我会采用两种方法中的一种,而决定实际上取决于你喜欢做什么。
选项 1
选择属性版本
var foo = client.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("f, collect(b) as bars")
.Return((f, bars) => new Foo
{
FooPropOne = f.As<Foo>().FooPropOne,
FooPropTwo = f.As<Foo>().FooPropTwo,
Bars = Return.As<List<Bar>>("bars")
}).Results.SingleOrDefault();
此版本允许您对带出的对象进行类型安全处理,在具有大量属性的 class 上确实限制了输入错误的可能性。这将使您返回Foo
实例,所以不需要做任何其他处理。
选项 2
post-加工所需版本的一点点
var notQuiteFoo = client.Cypher
.Match("(f:Foo)-[:FOOBAR]->(b:Bar)")
.With("f, collect(b) as bars")
.Return((f, bars) => new
{
Foo = f.As<Foo>(),
Bars = bars.As<List<Bar>>()
}).Results;
这节省了输入属性的时间,因此 class 大大节省了时间,还意味着如果您添加额外的属性,您无需记住更新查询。 但是你确实需要做一些post查询处理,比如:
IEnumerable<Foo> foos = notQuiteFoo.Results.Select(r => {r.Foo.Bars = r.Bars; return r.Foo;});
就个人而言 - 我喜欢 选项 2,因为它出现错别字的可能性较小,但我很欣赏这两者都不是您所追求的。