【发布时间】:2014-01-29 01:02:04
【问题描述】:
在 Neo4j 2.0 M06 中,我知道 CREATE UNIQUE 已被贬低并用 MERGE 和 MATCH 代替,但我发现很难看到如何使用它来创建唯一路径。
举个例子,我想创建一个
MERGE root-[:HAS_CALENDER]->(cal:Calender{name:'Booking'})-[:HAS_YEAR]->(year:Year{value:2013})-[:HAS_MONTH]-(month:Month{value:'January'})-[:HAS_DAY]->(day:Day{value:1})
ON CREATE cal
SET cal.created = timestamp()
ON CREATE year
SET year.created = timestamp()
ON CREATE month
SET month.created = timestamp()
ON CREATE day
SET day.created = timestamp()
意图是,当我尝试在日历中添加新日期时,它应该只创建年份和月份,如果它不存在,则只需添加到现有路径中。现在,当我运行查询时,我得到一个 STATEMENT_EXECUTION_ERROR
MERGE only supports single node patterns
我是否应该在这里执行多个语句来实现这一点。 所以问题是 Neo4j 处理这种情况的最佳方式是什么?
编辑
我确实稍微改变了我的方法,现在即使在进行了多次调用之后,我认为我的合并是在标签级别发生的,而不是试图限制到我提供的起始节点,因此我最终得到的节点是跨年和跨月共享,这不是我所期望的
如果有人能建议我如何获得如下所示的正确图表,我将不胜感激
我的 c# 代码有点像这样:
var qry = GraphClient.Cypher
.Merge("(cal:CalendarType{ Name: {calName}})")
.OnCreate("cal").Set("cal = {newCal}")
.With("cal")
.Start(new { root = GraphClient.RootNode})
.CreateUnique("(root)-[:HAS_CALENDAR]->(cal)")
.WithParams(new { calName = newCalender.Name, newCal = newCalender })
.Return(cal => cal.Node<CalenderType>());
var calNode = qry.Results.Single();
var newYear = new Year { Name = date.Year.ToString(), Value = date.Year }.RunEntityHousekeeping();
var qryYr = GraphClient.Cypher
.Merge("(year:Year{ Value: {yr}})")
.OnCreate("year").Set("year = {newYear}")
.With("year")
.Start(new { calNode })
.CreateUnique("(calNode)-[:HAS_YEAR]->(year)")
.WithParams(new { yr = newYear.Value, newYear = newYear })
.Return(year => year.Node<Year>());
var yearNode = qryYr.Results.Single();
var newMonth = new Month { Name = date.Month.ToString(), Value = date.Month }.RunEntityHousekeeping();
var qryMonth = GraphClient.Cypher
.Merge("(mon:Month{ Value: {mnVal}})")
.OnCreate("mon").Set("mon = {newMonth}")
.With("mon")
.Start(new { yearNode })
.CreateUnique("(yearNode)-[:HAS_MONTH]->(mon)")
.WithParams(new { mnVal = newMonth.Value, newMonth = newMonth })
.Return(mon => mon.Node<Month>());
var monthNode = qryMonth.Results.Single();
var newDay = new Day { Name = date.Day.ToString(), Value = date.Day, Date = date.Date }.RunEntityHousekeeping();
var qryDay = GraphClient.Cypher
.Merge("(day:Day{ Value: {mnVal}})")
.OnCreate("day").Set("day = {newDay}")
.With("day")
.Start(new { monthNode })
.CreateUnique("(monthNode)-[:HAS_DAY]->(day)")
.WithParams(new { mnVal = newDay.Value, newDay = newDay })
.Return(day => day.Node<Day>());
var dayNode = qryDay.Results.Single();
问候 基兰
【问题讨论】:
-
出于兴趣,但与问题无关,RunEntityHousekeeping 是做什么的?
-
@TathamOddie :嗯,这是我在插入之前需要做的一些常见任务,比如使用你的造雪机设置内部 ID 并暂时定义标签等,直到我想出一个更好的解决方案。尝试解决一个问题,即每次我尝试调用 MERGE 时我都会丢失 snowmaker 上的索引,因为我不确定该对象是否会在查询期间实际创建或与现有对象合并。
-
澄清点:你真的想把日子和
[:NEXT]关系联系起来吗?例如,看起来事件 2 实际上与 2010 有两次关联:(year 2010)-->(month 12)-->(day 31)-[:NEXT]->(day 1)-->(event 2)和(year 2010)-->(month 12)-->(day 31)-->(event 2)。我了解您希望事件在多天发生,但我觉得您的:NEXT关系可能会产生奇怪的副作用,具体取决于您的查询。例如,(事件 3)将出现在 2010 年以下的(伪)查询(month 12)-[*]-(:Event)中,这可能不是您的意图。
标签: neo4j cypher neo4jclient