我是 Neo4jClient 的作者。(免费赠送软件的人。)
Q1a:
“我可以使用 CRUD API 通过其 ID 查找节点 A,从 POCO 创建节点 B,创建 A 和 B 之间的关系”
Cypher 不仅是通往未来的道路,也是通往“现在”的道路。
从 Cypher 开始(有很多资源):
START user=node:user(Id: 1234)
CREATE user-[:INVITED]->(user2 { Id: 4567, Name: "Jim" })
Return user2
然后将其转换为 C#:
graphClient.Cypher
.Start(new { user = Node.ByIndexLookup("User", "Id", userId) })
.Create("user-[:INVITED]->(user2 {newUser})")
.WithParam("newUser", new User { Id = 4567, Name = "Jim" })
.Return(user2 => user2.Node<User>())
.Results;
这里有更多类似的例子:https ://github.com/Readify/Neo4jClient/wiki/cypher-examples
问题 1b:
“并在一个请求中将 B 的 ID 添加到旧索引中?”
不,Cypher 不支持旧索引。如果你真的想继续使用它们,那么你应该坚持使用 CRUD API。没关系:如果您想使用旧版索引,请使用旧版 API。
Q2。
“如果不是,还有什么替代方案?CRUD API 是否被视为遗留代码,我们是否应该转向基于 Cypher 的 Neo4j 2.0 方法?”
这正是你想要做的。Cypher,带有标签和自动索引:
// One time op to create the index
// Yes, this syntax is a bit clunky in C# for now
graphClient.Cypher
.Create("INDEX ON :User(Id)")
.ExecuteWithoutResults();
// Find an existing user, create a new one, relate them,
// and index them, all in a single HTTP call
graphClient.Cypher
.Match("(user:User)")
.Where((User user) => user.Id == userId)
.Create("user-[:INVITED]->(user2 {newUser})")
.WithParam("newUser", new User { Id = 4567, Name = "Jim" })
.ExecuteWithoutResults();
更多示例:https ://github.com/Readify/Neo4jClient/wiki/cypher-examples
Q3。
“这种基于 Cypher 的方法是否意味着我们失去了用于创建操作的 POCO 到节点的转换?这非常方便。”
正确的。但这就是我们所有人都想做的事情,Neo4j 的发展方向,Neo4jClient 的发展方向。
想一想 SQL(我假设你很熟悉)。您是否运行查询以查找节点的内部标识符,包括其在磁盘上的文件偏移量,然后在第二个查询中使用此内部标识符来操作它?不,您只需运行一个查询即可一次性完成所有操作。
现在,为什么人们喜欢传递Node<T>
或NodeReference
实例的一个常见用例是减少查询中的重复。这是一个合理的担忧,但是因为 .NET 中的流畅查询是不可变的,我们可以只构建一个基本查询:
public ICypherFluentQuery FindUserById(long userId)
{
return graphClient.Cypher
.Match("(user:User)")
.Where((User user) => user.Id == userId);
// Nothing has been executed here: we've just built a query object
}
然后像这样使用它:
public void DeleteUser(long userId)
{
FindUserById(userId)
.Delete("user")
.ExecuteWithoutResults();
}
或者,添加更多 Cypher 逻辑来删除所有关系:
然后像这样使用它:
public void DeleteUser(long userId)
{
FindUserById(userId)
.Match("user-[:?rel]-()")
.Delete("rel, user")
.ExecuteWithoutResults();
}
通过这种方式,您可以有效地重用引用,而不必一开始就将它们拉回电线。