我正在尝试在Neo4j http://blog.neo4j.org/2012/02/modeling-multilevel-index-in-neoj4.html
中构建此模型现在我需要一个查询来查明时间轴路径是否已经存在。问题是我似乎无法使节点成为可选节点,同时检查属性是否存在。
理想情况下我想要这个查询:
START a=node(2)
MATCH a:timeline -[?]-> b:time_year -[?]-> c:time_month -[?]-> d:time_day
WHERE b.year = 2013 AND c.month = 7 AND d.day = 28
RETURN b, c, d
但由于似乎不支持可选节点上的标签,我将使用此查询:
START a=node(2)
MATCH a:timeline -[?]-> b -[?]-> c -[?]-> d
WHERE b.year = 2013 AND c.month = 7 AND d.day = 28
RETURN b, c, d
如果没有WHERE子句,则会返回:
a b c
null null null
结果很好,因为我知道我必须制作年,月和日节点。但是如果没有WHERE子句,我就无法指定我希望渲染整个查询的日期无用。
我正在使用Neo4j 2.0.0-M03
更新: 澄清标签不起作用的原因。这是在一个新的数据库上运行。
在控制台中:
neo4j-sh (0)$ CREATE (n:timeline) RETURN n;
==> +-----------+
==> | n |
==> +-----------+
==> | Node[1]{} |
==> +-----------+
==> 1 row
==> Nodes created: 1
==> Labels added: 1
==> 967 ms
neo4j-sh (0)$ START a=node(1) MATCH a:timeline -[?]-> b:time_year -[?]-> c:time_month -[?]-> d:time_day WHERE b.year = 2013 AND c.month = 7 AND d.day = 28 RETURN b as year, c as month, d as day;
==> Unrecognized option '['
在数据浏览器中:
START a=node(1) MATCH a:timeline -[?]-> b:time_year -[?]-> c:time_month -[?]-> d:time_day WHERE b.year = 2013 AND c.month = 7 AND d.day = 28 RETURN b as year, c as month, d as day;
Returned 0 rows. Query took 138ms
Not found
There is no data matching your query in the database.
我刚刚发现这些查询在我的代码中有效,但在Neo4j控制台或数据浏览器中却没有。我认为那些将是“完美无瑕”,因此之前没有在我的代码中测试这些查询。同样奇怪的是,控制台和数据浏览器给出了不同的结果。在start而不是node(1)选择节点(*)并没有什么区别。
更新2 : 彼得·纽鲍尔(Peter Neubauer)发布的示例要点让我玩了一些。问题是这个例子每次都返回。虽然我想使返回的列可选。所以在这个例子中我希望Query3返回:
Columns: year, month, day
Data: 2010, null, null
但它返回:
Query took 264 ms and returned no rows.
当我将属性设为可选时,如下所示:
START a=node(*)
MATCH a:timeline -[?]-> b:time_year -[?]-> c:time_month -[?]-> d:time_day
WHERE b.year? = 2010 AND c.month? = 1 AND d.day? = 1
RETURN b AS year, c AS month, d AS day
我得到(在gists网站上):
Error: java.lang.NullPointerException
这是踢球者:这只发生在firefox上,在chrome上返回:查询花了1毫秒并且没有返回任何行。
然后这个查询:
START a=node(*)
MATCH a:timeline -[?]-> b -[?]-> c -[?]-> d
WHERE b.year? = 2010 AND c.month? = 1 AND d.day? = 1
RETURN b AS year, c AS month, d AS day
返回:
Columns: year, month, day
Data: (9:time_year {name:"Year 2010", year:2010}), [empty table cell], [empty table cell]
这是我想要的结果(但之后没有使用标签)
然后在Chrome上进行相同的查询:
Query took 4 ms and returned no rows.
所以到目前为止我的结论是:
有5种不同的环境会产生不同的结果:
我还没有尝试过:
所以我对查询和一堆环境有很多变化。也许这可以通过一种方式编写脚本,以便在不同的环境中运行查询并返回结果。然后我可以将结果放在一个表中,其中一个轴是环境,另一个是测试中的查询。
答案 0 :(得分:1)
为每个可选标签约束执行此操作以解决此问题
CASE
WHEN b IS NOT NULL AND ANY(x IN LABELS(b) WHERE x="time_year") THEN b
ELSE NULL
END AS newB
由于b是任何类型的节点,这将确保如果存在,则它是正确的标签。它有点冗长,但很好。
- edit-- 基于flip关于索引的评论,我做了以下内容:(执行计划基于第二次运行每个查询)
CREATE INDEX ON :time_year(year);
create
(_7:timeline ),
(_8:time_year {year:2010}),
(_9:timeline ),
_9-[:HAS_YEAR]->_8;
第一个想法
MATCH a:timeline WITH a
MATCH a-[?]->b
WITH a, b, CASE WHEN b IS NOT NULL AND ANY (x IN LABELS(b)
WHERE x="time_year") THEN b ELSE NULL END AS newB
WHERE newB.year? = 2010
RETURN a, newB AS year
Detailed Query Results
Query Results
+--------------------------------+
| a | year |
+--------------------------------+
| Node[7]{} | Node[8]{year:2010} |
| Node[9]{} | |
+--------------------------------+
2 rows
2 ms
Execution Plan
ColumnFilter(symKeys=["a", "b", "newB", "year"], returnItemNames=["a", "year"], _rows=2, _db_hits=0)
Extract(symKeys=["a", "b", "newB"], exprKeys=["year"], _rows=2, _db_hits=0)
Filter(pred="nullable([($anonfun$nullableProperty$3$$anonfun$apply$21$$anon$1,true)],[$anonfun$nullableProperty$3$$anonfun$apply$21$$anon$1 == Literal(2010)])", _rows=2, _db_hits=2)
ColumnFilter(symKeys=["a", "b", " UNNAMED33", "newB"], returnItemNames=["a", "b", "newB"], _rows=2, _db_hits=0)
Extract(symKeys=["a", "b", " UNNAMED33"], exprKeys=["newB"], _rows=2, _db_hits=0)
PatternMatch(g="(a)-[' UNNAMED33']-(b)", _rows=2, _db_hits=1)
PatternMatch(g="", _rows=2, _db_hits=0)
Filter(pred="hasLabel(a: timeline)", _rows=2, _db_hits=0)
NodeByLabel(label="timeline", identifier="a", _rows=2, _db_hits=0)
第二个想法
MATCH a:timeline WITH a
MATCH a-[?]->b
WHERE b.year? = 2010
RETURN a, b AS year
Detailed Query Results
Query Results
+--------------------------------+
| a | year |
+--------------------------------+
| Node[7]{} | Node[8]{year:2010} |
| Node[9]{} | |
+--------------------------------+
2 rows
2 ms
Execution Plan
ColumnFilter(symKeys=["a", "b", " UNNAMED33", "year"], returnItemNames=["a", "year"], _rows=2, _db_hits=0)
Extract(symKeys=["a", "b", " UNNAMED33"], exprKeys=["year"], _rows=2, _db_hits=0)
Filter(pred="nullable([($anonfun$nullableProperty$3$$anonfun$apply$21$$anon$1,true)],[$anonfun$nullableProperty$3$$anonfun$apply$21$$anon$1 == Literal(2010)])", _rows=2, _db_hits=2)
PatternMatch(g="(a)-[' UNNAMED33']-(b)", _rows=2, _db_hits=3)
PatternMatch(g="", _rows=2, _db_hits=0)
Filter(pred="hasLabel(a: timeline)", _rows=2, _db_hits=0)
NodeByLabel(label="timeline", identifier="a", _rows=2, _db_hits=0)
如果我们在Cypher中只提供NULLIF功能,那么这会让它变得更清晰一些。虽然在任何一种情况下检查关系上的节点都不会使用任何索引。
答案 1 :(得分:0)
从这个页面得到答案:http://grokbase.com/t/gg/neo4j/137qbdyn14/use-label-in-start
START a=node(2)
MATCH a:timeline -[?]-> b -[?]-> c -[?]-> d
WHERE b.year? = 2013 AND c.month? = 7 AND d.day? = 28
RETURN b, c, d
然而关于标签的其他问题现在仍然是个谜。
答案 2 :(得分:0)
这个问题的正确答案是,Neo4j 2.0.0里程碑03中没有此功能或缺少(错误?)。但现在已添加到Neo4j 2.0.0 Milestone 05中。{{1 }}
(我还没有测试过)
答案 3 :(得分:-1)
我对此做了一个图表要点,请参阅http://gist.neo4j.org/?6113785,似乎标签正在运作。想做出贡献并澄清一下吗?