我的持久层基本上使用Neo4jClient来访问Neo4j 1.9.4数据库.更具体地说,要创建我IGraphClient#Create()在Neo4jClient的CRUD API中使用的节点并查询图形,我使用Neo4jClient的Cypher支持.
一切都很好,直到我的一个朋友指出,对于每个查询,我基本上做了两个HTTP请求:
对于读取操作,我做了显而易见的事情并将索引查找移动到我的Start()调用中,即:
GraphClient.Cypher
.Start(new { user = Node.ByIndexLookup("User", "Id", userId) })
// ... the rest of the query ...
Run Code Online (Sandbox Code Playgroud)
另一方面,对于创建操作,我认为这实际上是不可能的.我的意思是:该Create()方法采用POCO,几个关系实例和几个索引条目,以便在一个事务/ HTTP请求中创建节点,其关系及其索引条目.问题是您传递给关系实例的节点引用:它们来自哪里?从以前的HTTP请求,对吗?
我的问题:
此外,Neo4jClient的文档可以更新,因为坦白说,它很差.我确实认识到Readify还提供商业支持,以便解释事情.
谢谢!
我是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
Run Code Online (Sandbox Code Playgroud)
然后将其转换为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;
Run Code Online (Sandbox Code Playgroud)
这里有更多类似的例子:https://github.com/Readify/Neo4jClient/wiki/cypher-examples
Q1B:
"并在一个请求中将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();
Run Code Online (Sandbox Code Playgroud)
更多示例: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
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
public void DeleteUser(long userId)
{
FindUserById(userId)
.Delete("user")
.ExecuteWithoutResults();
}
Run Code Online (Sandbox Code Playgroud)
或者,添加更多Cypher逻辑来删除所有关系:
然后像这样使用它:
public void DeleteUser(long userId)
{
FindUserById(userId)
.Match("user-[:?rel]-()")
.Delete("rel, user")
.ExecuteWithoutResults();
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以有效地重用引用,但无需首先将它们拉回到线路中.
| 归档时间: |
|
| 查看次数: |
1415 次 |
| 最近记录: |