2013-11-15 41 views
0

我有這樣的查詢:如何使CREATE UNIQUE與子查詢一起工作?

MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
    LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
    SKIP 4 LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
    SKIP 8 LIMIT 1 
RETURN left, right 
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel; 

一般情況下,我只是創建一個數據集,這樣我以後可以使用它在CREATE UNIQUE指令。
很明顯,這不起作用 - 查詢分析器說,我只能使用RETURN子句一次。 我的問題是 - 在這種情況下如何組成數據集?我試圖分配一個別名,並在CREATE UNIQUE中使用它 - 無法讓它工作。我究竟做錯了什麼?這種情況甚至可能嗎?

+0

我不明白你在做什麼,但你的查詢中唯一嚴格的非法返回是在創建子句之前。如果你刪除它,你的查詢是否符合你的期望? – jjaderberg

+0

@jjaderberg不,它表示聯合中的所有子查詢必須具有相同的列名。 – chester89

+0

這很有道理。但爲什麼你以前回來過這麼多次?你是否在積累節點,以便你可以用一個創建獨特的子句創建許多關係? Union會聯合回答許多查詢,但在你的情況下,你應該能夠用WITH WITH子句收集和運送'left'和'right',創建關係,並在最後返回一次,不是嗎? – jjaderberg

回答

1

我可能會誤解你以後的事情,但是當我看着你的查詢時,這就是我發生的事情。

首先,這裏是對您的查詢進行修改,該查詢使用SKIPLIMIT而沒有RETURNUNION

MATCH left, right 
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6] 
WITH left, right 
    LIMIT 1 
CREATE UNIQUE left-[rel:FRIEND]->right 
WITH [rel] as rels //If you want to return the relationship later you can put it in a collection and bring it WITH 
MATCH left, right 
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6] 
WITH left, right, rels 
    SKIP 4 LIMIT 1 
CREATE UNIQUE left-[rel:FRIEND]->right 
WITH rels + [rel] as rels 
MATCH left, right 
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6] 
WITH left, right, rels 
    SKIP 8 LIMIT 1 
CREATE UNIQUE left-[rel:FRIEND]->right 
WITH rels + [rel] as rels 
RETURN LENGTH(rels), rels // You can return the relationships here but SKIP/LIMIT does its job also if you don't return anything 

但是這個查詢有點瘋狂。這實際上是三個查詢,其中兩個已被人爲擠壓爲第一個子查詢。它在每個子查詢中重新匹配相同的節點,並且通過這種方式運行查詢確實沒有獲得任何結果,而不是單獨進行(它實際上比較慢,因爲在每個子查詢中,您匹配的也是您不知道的節點) 。

因此,我的第一個建議是,當通過id獲取節點時,使用START而不是MATCH...WHERE。現在,查詢將數據庫中的每個節點都綁定爲「左」,然後將數據庫中的每個節點都綁定爲「正確」,然後過濾出所有綁定到「左」的節點,這些節點不適合條件WHERE條款,然後相同的「權利」。由於這部分查詢重複了三次,數據庫中的所有節點總共綁定了六次。創建三種關係的成本很高。如果你使用START,你可以綁定你想要的節點。這並不能真正回答你的問題,但它會更快,並且查詢會更清晰。因此,使用START通過其內部ID獲取節點。

START left = node(1,2,3), right = node(4,5,6) 

我想到的第二件事是當你匹配模式時節點和'路徑'或'結果項目'之間的區別。當您將「左」中的三個節點和「右」中的其他三個節點綁定在一起時,您沒有三個結果項目,而是九個。對於在「左」中綁定的每個節點,您會得到三個結果,因爲有三個可能的「正確」來結合它。如果你想把每個「左」與每個「右」聯繫起來,那麼很好。但我認爲你要找的是(1),(4),(2),(5),(2),(5),(3),(6)的結果項目,儘管將​​一個查詢中的三個「左」節點和三個「右」節點與節點ID的集合綁定似乎很方便,然後你必須做所有的篩選以擺脫6個不需要的匹配。查詢變得複雜而繁瑣,而且實際上比單獨運行查詢要慢。另一種說法是說(1)-[:FRIEND]->(4)是一種截然不同的模式,與您正在創建的其他模式不相關(相關)。如果你想創建(1)-[:FRIEND]->(2)<-[:FRIEND]-(3),那麼你會想要一起處理這三個節點。也許你只是在探索密碼的邊緣使用,但我想我應該指出。順便說一下,以這種方式使用SKIPLIMIT是一個關鍵,他們並不真正用於模式匹配和過濾。這也是不可預測的,除非你也使用ORDER BY,因爲不能保證結果將按照一定的順序。你不知道得到的是哪個結果項目。無論如何,在這種情況下,我認爲在三個單獨的查詢中綁定節點並創建關係會更好。

START left = node(1), right = node(4) 
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel 

START left = node(2), right = node(5) 
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel 

START left = node(3), right = node(6) 
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel 

既然你已經知道你想要的三雙,而不是,比方說,(1),(4)(1),(5)(1),(6)這將是有意義的查詢只是那些對,最簡單的方法是分別查詢。因爲三個查詢在結構上是相同的,只有屬性值不同(如果id被認爲是一個屬性),您可以通過概括或匿名區分它們的參數(即使用參數)來簡化查詢。

START left = node({leftId}), right = node({rightId}) 
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel 

parameters: {leftId:1, rightId:4}, {leftId:2, rightId:5}, {leftId:3, rightId:6} 

由於結構相同,密碼可以緩存執行計劃。這使得性能良好,並且查詢整潔,可維護,並且如果稍後想要在其他節點對上執行相同的操作,可以輕鬆擴展。