Neo4j:合并复制查询中的三个节点之一
Neo4j: Merge duplicating one of three nodes in a query
正如我在另一个 post 上所说的那样,我正在从 SQL 服务器迁移到 Neo4j,所以我正在与学习曲线作斗争。我在搜索 Whosebug 和 google 来回答我的问题方面做得相当好,但我偶然发现了一个奇怪的查询结果,该查询没有意义。
C#代码:
public void AddMarketInfo(MarketInfo mi)
{
Bid bid = mi.Bid;
Ask ask = mi.Ask;
var query = clientConnection.Cypher
.Merge("(newbid:Bid { ID: {bID} })")
.OnCreate()
.Set("newbid = {bid}")
.WithParams(new
{
bID = bid.ID,
bid
})
.Merge("(newask:Ask { ID: {aID} })")
.OnCreate()
.Set("newask = {ask}")
.WithParams(new
{
aID = ask.ID,
ask
})
.Merge("(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })")
.OnCreate()
.Set("newMarketInfo = {mi}")
.WithParams(new
{
id = mi.ID,
bidID = bid.ID,
askID = ask.ID,
mi
})
.CreateUnique("(newask)-[rA:Ask_Input_Data]->(newMarketInfo)")
.CreateUnique("(newbid)-[rB:Bid_Input_Data]->(newMarketInfo)");
query.ExecuteWithoutResults();
}
我目前正在调试程序,所以这条语句对同一个数据执行了多次。是的,我现在进入数据库并删除所有节点。
创建"Bid"节点和"Ask"节点时,它成功地与现有节点合并,但"MarketInfo"节点正在被复制。
有什么想法吗?
编辑 2:修改查询
所以我在 neo4j 文档中做了更多阅读:
https://neo4j.com/docs/developer-manual/current/cypher/clauses/merge/#query-merge-on-create-on-match
他们提供的例子是:
与 ON CREATE 和 ON MATCH 合并
如果需要创建节点,则合并节点并设置属性。
查询。
MERGE (keanu:Person { name: 'Keanu Reeves' })
ON CREATE SET keanu.created = timestamp()
ON MATCH SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen
查询创建 'keanu' 节点,并设置创建时间的时间戳。如果 'keanu' 已经存在,则会设置不同的 属性。
所以我将代码修改为 "do the same":
var query = graphClient.Cypher
.Merge("(newbid:Bid { ID: {bID} })")
.OnMatch()
.Set("newbid = {bid}")
.OnCreate()
.Set("newbid = {bid}")
.WithParams(new
{
bID = bid.ID,
bid
})
.Merge("(newask:Ask { ID: {aID} })")
.OnMatch()
.Set("newask = {ask}")
.OnCreate()
.Set("newask = {ask}")
.WithParams(new
{
aID = ask.ID,
ask
})
.Merge("(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })")
.OnCreate()
.Set("newMarketInfo = {mi}")
.WithParams(new
{
id = mi.ID,
bidID = bid.ID,
askID = ask.ID,
mi
})
.Merge("(newask)-[rA:Ask_Input_Data]->(newMarketInfo)")
.Merge("(newbid)-[rB:Bid_Input_Data]->(newMarketInfo)");
query.ExecuteWithoutResultsAsync();
然而,节点 MarketInfo 节点仍在复制。我想我现在正朝着正确的方向前进,但是......我仍然缺少一些东西。
根据提供的信息,听起来 很可能 "(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })"
每次 [=48] 都有不同的 ID
值=] 你的代码。
另一个选项是 mi
params 值的值改变 节点的 { ID: {id}, ASK: {askID}, BID: {bidID} }
值。换句话说/举个例子,可能是您在 { ID: {1}, ASK: {2}, BID: {3} }
上合并,然后在 ON CREATE
上合并,立即设置 "newMarketInfo = {mi}"
,这会将节点的值更改为 { ID: {2}, ASK: {3}, BID: {4}, exampleValue: {5} }
。在这种情况下,合并将总是 创建一个新节点,但是当您检查结果时,创建的节点看起来是相同的。有道理吗?
更新
您添加的照片显示您的 MarketInfo
节点没有 ASK
或 BID
属性(您要合并的属性)。假设这些属性不应该是 null
。这让我认为我上面的第二个假设解释了正在发生的事情。要对此进行测试,您可以尝试消除
.OnCreate().Set("newMarketInfo = {mi}")
您查询的一部分。在这种情况下,请查看您的合并在数据库中持久存在的节点。节点是否具有 ASK
/ BID
属性?如果是,那么您已经找到问题所在。您还可以查看 运行 在这种情况下查询两次是否会添加第二个节点。如果不是,问题肯定出在 ON CREATE
子句上。
这就是问题所在,这让我很烦恼...
您不能使用 "ID" 作为对象的参数。您可以使用 "Id" 或 "id" 或 "iD",但不能使用 "ID"。一旦我切换到使用 "Id",该节点就再也没有被复制过。
正如我在另一个 post 上所说的那样,我正在从 SQL 服务器迁移到 Neo4j,所以我正在与学习曲线作斗争。我在搜索 Whosebug 和 google 来回答我的问题方面做得相当好,但我偶然发现了一个奇怪的查询结果,该查询没有意义。
C#代码:
public void AddMarketInfo(MarketInfo mi)
{
Bid bid = mi.Bid;
Ask ask = mi.Ask;
var query = clientConnection.Cypher
.Merge("(newbid:Bid { ID: {bID} })")
.OnCreate()
.Set("newbid = {bid}")
.WithParams(new
{
bID = bid.ID,
bid
})
.Merge("(newask:Ask { ID: {aID} })")
.OnCreate()
.Set("newask = {ask}")
.WithParams(new
{
aID = ask.ID,
ask
})
.Merge("(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })")
.OnCreate()
.Set("newMarketInfo = {mi}")
.WithParams(new
{
id = mi.ID,
bidID = bid.ID,
askID = ask.ID,
mi
})
.CreateUnique("(newask)-[rA:Ask_Input_Data]->(newMarketInfo)")
.CreateUnique("(newbid)-[rB:Bid_Input_Data]->(newMarketInfo)");
query.ExecuteWithoutResults();
}
我目前正在调试程序,所以这条语句对同一个数据执行了多次。是的,我现在进入数据库并删除所有节点。
创建"Bid"节点和"Ask"节点时,它成功地与现有节点合并,但"MarketInfo"节点正在被复制。
有什么想法吗?
编辑 2:修改查询
所以我在 neo4j 文档中做了更多阅读:
https://neo4j.com/docs/developer-manual/current/cypher/clauses/merge/#query-merge-on-create-on-match
他们提供的例子是:
与 ON CREATE 和 ON MATCH 合并 如果需要创建节点,则合并节点并设置属性。
查询。
MERGE (keanu:Person { name: 'Keanu Reeves' })
ON CREATE SET keanu.created = timestamp()
ON MATCH SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen
查询创建 'keanu' 节点,并设置创建时间的时间戳。如果 'keanu' 已经存在,则会设置不同的 属性。
所以我将代码修改为 "do the same":
var query = graphClient.Cypher
.Merge("(newbid:Bid { ID: {bID} })")
.OnMatch()
.Set("newbid = {bid}")
.OnCreate()
.Set("newbid = {bid}")
.WithParams(new
{
bID = bid.ID,
bid
})
.Merge("(newask:Ask { ID: {aID} })")
.OnMatch()
.Set("newask = {ask}")
.OnCreate()
.Set("newask = {ask}")
.WithParams(new
{
aID = ask.ID,
ask
})
.Merge("(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })")
.OnCreate()
.Set("newMarketInfo = {mi}")
.WithParams(new
{
id = mi.ID,
bidID = bid.ID,
askID = ask.ID,
mi
})
.Merge("(newask)-[rA:Ask_Input_Data]->(newMarketInfo)")
.Merge("(newbid)-[rB:Bid_Input_Data]->(newMarketInfo)");
query.ExecuteWithoutResultsAsync();
然而,节点 MarketInfo 节点仍在复制。我想我现在正朝着正确的方向前进,但是......我仍然缺少一些东西。
根据提供的信息,听起来 很可能
"(newMarketInfo:MarketInfo { ID: {id}, ASK: {askID}, BID: {bidID} })"
每次 [=48] 都有不同的ID
值=] 你的代码。另一个选项是
mi
params 值的值改变 节点的{ ID: {id}, ASK: {askID}, BID: {bidID} }
值。换句话说/举个例子,可能是您在{ ID: {1}, ASK: {2}, BID: {3} }
上合并,然后在ON CREATE
上合并,立即设置"newMarketInfo = {mi}"
,这会将节点的值更改为{ ID: {2}, ASK: {3}, BID: {4}, exampleValue: {5} }
。在这种情况下,合并将总是 创建一个新节点,但是当您检查结果时,创建的节点看起来是相同的。有道理吗?
更新
您添加的照片显示您的 MarketInfo
节点没有 ASK
或 BID
属性(您要合并的属性)。假设这些属性不应该是 null
。这让我认为我上面的第二个假设解释了正在发生的事情。要对此进行测试,您可以尝试消除
.OnCreate().Set("newMarketInfo = {mi}")
您查询的一部分。在这种情况下,请查看您的合并在数据库中持久存在的节点。节点是否具有 ASK
/ BID
属性?如果是,那么您已经找到问题所在。您还可以查看 运行 在这种情况下查询两次是否会添加第二个节点。如果不是,问题肯定出在 ON CREATE
子句上。
这就是问题所在,这让我很烦恼...
您不能使用 "ID" 作为对象的参数。您可以使用 "Id" 或 "id" 或 "iD",但不能使用 "ID"。一旦我切换到使用 "Id",该节点就再也没有被复制过。