2017-08-08 65 views
1

我有一個使用Neo4j數據庫的大型應用程序。有幾十種方法可以支持Cypher查詢。爲了刪除重複的代碼,如果每個方法都存儲它自己的完整查詢,那麼我就創建了私有方法來構建查詢的小常用塊。例如,像一個方法:通過添加WHERERETURN語句來建立一個完整的查詢方法有沒有辦法將多個WHERE語句鏈接在一起,而無需在Neo4j中切換到AND?

MATCH (node:label) 

然後將這些方法調用如下:

MatchNodesWithLabel(string label) 

將返回像部分查詢。這是一個小例子,有一些方法可以匹配和過濾整套節點和關係。

,就會出現問題,當多個WHERE語句需要被鏈接在一起。 Cypher支架不允許WHERE聲明遵循WHERE聲明:

// Invalid 
MATCH (node) 
WHERE node:label 
WHERE node.property = value 
... 

所以過去的第一WHERE任何方法都必須插入一個AND語句來代替:

// Valid 
MATCH (node) 
WHERE node:label 
AND node.property = value 
AND ... 

這將創建一個方法排序問題,其中其他方法不能使用某些方法。插入WHERE語句(方法Where())的方法必須先於And()方法。 Where()方法然後可以不是And()方法之後被使用,並且And()方法不能之前Where()方法中使用。

下面是一些可能(但最終打破)的解決方案,我想出瞭解決這個問題的排序:

  1. 重複每Where()法成等價的AndWhere()方法,做同樣的過濾,但使用AND而不是WHERE。然後在調用代碼中,先使用一個Where()方法,然後使用AndWhere()方法。
    • 這不是因爲重複的代碼可接受的解決方案,並且因爲它調用代碼複雜化。它只是將方法排序問題移動到調用代碼,而不是解決問題。我希望能夠添加Where()電話時,我想,不用考慮我的方法如何排序
  2. 所有其他調用之前添加一個WHERE true聲明,然後盡一切Where()方法插入AND聲明。
    • 這隻有在調用代碼的方法是明確下令工作。所有MATCH方法必須先於WHERE true,否則你可以用暗號查詢像結束:這是無效的,因爲AND遵循MATCH沒有WHERE
      MATCH (node) WHERE true AND node:type MATCH (somethingElse) AND somethingElse.property = value
      。所以方法排序的責任又一次轉移到了調用代碼上。有了這個解決方案,每次開始一系列新的過濾調用時,您都必須手動添加WHERE true
  3. 解析現有的查詢,以確定是否一個WHEREAND應在每Where()方法的開始使用。
    • 起初看起來不錯,你所要做的就是檢查existingQuery.Contains("WHERE"),如果它是真的,請插入AND。然而這與#2有同樣的問題。如果插入新的MATCH語句,該檢查仍然會返回true,但查詢不會處於AND是有效語句的狀態。因此,您必須在查詢中進一步解析,檢查MATCHWHERE語句,並且您必須跟蹤它們發生的順序等等。這太複雜了。

是在任何地方插入一些Neo4j的語法,允許一個WHERE,或查詢的建築解決方案,我碰到有沒有一些?

回答

2

在每WHERE聲明前添加WITH *

WITH *將會將查詢中已經存在的所有已命名的Cypher標識符轉換爲基本上是新查詢的命名。

所以查詢最終會看起來像:

MATCH (node) 
WITH * 
WHERE ... 
WITH * 
WHERE ... 
MATCH (somethingElse) 
WITH * 
WHERE ... 

這使得WHERE要在查詢的任何地方插入。

因此,每個Where()方法將插入WITH * WHERE而不是僅僅WHEREAND

重要注意事項:這會降低查詢速度。每個WITH是一個投影,投影並不是免費的。在我的測試中,使用WITH * WHERE的查詢比等效的WHERE ... AND查詢慢30% - 50%。

這絕對是一個醜陋的解決方案。希望有一個更好的解決方案,其速度與查詢速度一樣快,不會混淆查詢文本,但只要速度和查詢可讀性是可以接受的犧牲,該解決方案就能正常工作。

編輯:我發現這個解決方案也忽略了WHERE語句中的索引!這使得這些查詢的性能對於大型數據集來說無法接受地慢。我強烈建議不要使用這個技巧,而是犧牲一些代碼可讀性或代碼重複以獲得不錯的性能。

1

您的代碼可以有2個系列:說matcheswheres。您的MatchX()和WhereY()方法可以將適當的數據附加到它們各自的集合中。當您準備好提交查詢時,可以從這些集合中的數據中生成MATCHWHERE子句。

相關問題