2016-03-31 110 views
1

我在Neo4j查詢中遇到問題。假設我有一個名爲App的節點類型。 App節點具有「m_id」和「info」字段。我想建立一個查詢來創建字段「info」相等的節點之間的關係。在Neo4j查詢中CYPHER 2.3的性能

這是查詢:

MATCH (a:App {m_id:'SOME_VALUE' }),(b:App {info: a.info}) WHERE ID(a)<>ID(b) AND NOT (b)-[:INFO]->(a) MERGE (a)-[r:INFO]->(b) RETURN b.m_id; 

我也有兩個字段的索引:

CREATE CONSTRAINT ON (a:App) ASSERT a.m_id IS UNIQUE; 
CREATE INDEX ON :App(info); 

但事實是我在App的所有記錄變得非常慢查詢,訪問節點。

這是查詢的輪廓:

+---------------+--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| Operator  | Rows | DB Hits | Identifiers  | Other                               | 
+---------------+--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +ColumnFilter |  0 |  0 | b.m_id   | keep columns b.m_id                           | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +Extract  |  0 |  0 | a, b, b.m_id, r | b.m_id                               | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +Merge(Into) |  0 |  1 | a, b, r   | (a)-[r:INFO]->(b)                            | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +Eager  |  0 |  0 | a, b   |                                | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +Filter  |  0 | 2000000 | a, b   | Ands(b.info == a.info, NOT(IdFunction(a) == IdFunction(b)), NOT(nonEmpty(PathExpression((b)-[anon[104]:INFO]->(a), true)))) | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +SchemaIndex | 184492 | 1000000 | a, b   | { AUTOSTRING0}; :App(m_id)                         | 
| |    +--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 
| +NodeByLabel | 184492 | 1000001 | b    | :App                               | 
+---------------+--------+---------+-----------------+--------------------------------------------------------------------------------------------------------------------------------+ 

回答

1

嘗試通過自身尋找a,使用WITH條款把a.info到用於由單獨的MATCH子句b,作爲一個臨時變量:

MATCH (a:App { m_id:'SOME_VALUE' }) 
WITH a, a.info AS a_info 
MATCH (b:App { info: a_info }) 
WHERE a <> b AND NOT (b)-[:INFO]->(a) 
MERGE (a)-[r:INFO]->(b) 
RETURN b.m_id; 

似乎在比較2個節點的屬性時,往往不會使用索引。使用a_info消除了這種障礙。

如果上面的分佈圖顯示一個或兩個指標都沒有使用,你可以嘗試添加索引提示:

MATCH(:

MATCH (a:App { m_id:'SOME_VALUE' }) 
USING INDEX a:App(m_id) 
WITH a, a.info AS a_info 
MATCH (b:App { info: a_info }) 
USING INDEX b:App(info) 
WHERE a <> b AND NOT (b)-[:INFO]->(a) 
MERGE (a)-[r:INFO]->(b) 
RETURN b.m_id; 
+0

這是不夠好,它分爲兩個比賽。 2.3中不需要中間WITH或表達式別名 –

+0

您的解決方案也可以。 –

0

我使用可選的MATCH找出解決的辦法a:App {m_id:'SOME_VALUE'})可選MATCH(a),(b:App {info:a.info})WHERE ID(a)<> ID(b)AND NOT(b) - [:INFO] - >(a)MERGE(a) - [r:INFO] - >(b)RETURN b.m_id;

這是查詢的輪廓:

+----------------+------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| Operator  | Rows | DB Hits | Identifiers  | Other                          | 
+----------------+------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +ColumnFilter | 0 |  0 | b.m_id   | keep columns b.m_id                      | 
| |    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +Extract  | 0 |  0 | a, b, b.m_id, r | b.m_id                          | 
| |    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +Merge(Into) | 0 |  1 | a, b, r   | (a)-[r:INFO]->(b)                       | 
| |    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +Eager   | 0 |  0 | a, b   |                           | 
| |    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +OptionalMatch | 0 |  0 | a, b   |                           | 
| |\    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| | +Filter  | 0 |  0 | a, b   | Ands(NOT(IdFunction(a) == IdFunction(b)), NOT(nonEmpty(PathExpression((b)-[anon[109]:INFO]->(a), true)))) | 
| | |   +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| | +SchemaIndex | 0 |  0 | a, b   | a.info; :App(info)                      | 
| | |   +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| | +Argument | 0 |  0 | a    |                           | 
| |    +------+---------+-----------------+------------------------------------------------------------------------------------------------------------+ 
| +SchemaIndex | 0 |  1 | a    | { AUTOSTRING0}; :App(m_id)                    | 
+----------------+------+---------+-----------------+------------------------------------------------------------------------------------------------------------+