選取您的 Cookie 偏好設定

我們使用提供自身網站和服務所需的基本 Cookie 和類似工具。我們使用效能 Cookie 收集匿名統計資料,以便了解客戶如何使用我們的網站並進行改進。基本 Cookie 無法停用,但可以按一下「自訂」或「拒絕」以拒絕效能 Cookie。

如果您同意,AWS 與經核准的第三方也會使用 Cookie 提供實用的網站功能、記住您的偏好設定,並顯示相關內容,包括相關廣告。若要接受或拒絕所有非必要 Cookie,請按一下「接受」或「拒絕」。若要進行更詳細的選擇,請按一下「自訂」。

重寫 Cypher 查詢以在 Neptune 上的 OpenCpher 中執行

焦點模式
重寫 Cypher 查詢以在 Neptune 上的 OpenCpher 中執行 - Amazon Neptune

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

OpenCypher 語言是屬性圖的宣告式查詢語言,最初由 Neo4j 開發,然後在 2015 年成為開放原始碼,並在 Apache 2 開放原始碼授權下投入 OpenCypher 專案。在 AWS,我們相信開放原始碼對每個人都有益,而且我們致力於將開放原始碼的價值帶給客戶,以及將 的卓越營運 AWS 提供給開放原始碼社群。

OpenCypher 語法記載於 Cypher 查詢語言參考第 9 版

由於 OpenCypher 包含 Cypher 查詢語言的語法和功能子集,因此某些遷移案例需要以 OpenCypherr 相容的格式重寫查詢,或檢查替代方法以實現所需的功能。

本節包含處理常見差異的建議,但它們絕不是全面的。您應該使用這些重寫徹底測試任何應用程式,以確保結果就是您預期的。

重寫 NoneAllAny 述詞函數

這些函數不是 openCypher 規格的一部分。可比較的結果可以在 OpenCypher 中使用清單理解來實現。

例如,尋找從節點 Start 到節點 End 的所有路徑,但不允許任何行程通過類別屬性為 D 的節點:

# Neo4J Cypher code match p=(a:Start)-[:HOP*1..]->(z:End) where none(node IN nodes(p) where node.class ='D') return p # Neptune openCypher code match p=(a:Start)-[:HOP*1..]->(z:End) where size([node IN nodes(p) where node.class = 'D']) = 0 return p

清單理解可以實現這些結果,如下所示:

all => size(list_comprehension(list)) = size(list) any => size(list_comprehension(list)) >= 1 none => size(list_comprehension(list)) = 0

在 openCypher 中重寫 Cypher reduce() 函數

reduce() 函數不是 openCypher 規格的一部分。它通常用來從清單內的元素建立資料的彙總。在許多情況下,您可以使用清單理解和 UNWIND 子句的組合來實現類似的結果。

例如,在安克雷奇 (ANC) 與奧斯汀 (AUS) 之間具有一到三個停靠站的路徑上,下列 Cypher 查詢會找出所有位於這些路徑上的機場,並傳回每條路徑的總距離:

MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'}) RETURN p, reduce(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist ORDER BY totalDist LIMIT 5

您可以在 OpenCypher 為 Neptune 編寫相同的查詢,如下所示:

MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'}) UNWIND [i in relationships(p) | i.dist] AS di RETURN p, sum(di) AS totalDist ORDER BY totalDist LIMIT 5

在 openCypher 中重寫 Cypher FOREACH 子句

FOREACH 子句不是 openCypher 規格的一部分。它通常用來在查詢過程中更新資料,通常是從路徑內的彙總或元素中更新資料。

作為一個路徑範例,在安克雷奇 (ANC) 與奧斯汀 (AUS) 之間不超過兩個停靠站的路徑上,找出所有位於該路徑的機場,並對每個機場設定已訪問屬性:

# Neo4J Example MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'}) FOREACH (n IN nodes(p) | SET n.visited = true) # Neptune openCypher MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'}) WITH nodes(p) as airports UNWIND airports as a SET a.visited=true

另一個範例是:

# Neo4J Example MATCH p=(start)-[*]->(finish) WHERE start.name = 'A' AND finish.name = 'D' FOREACH (n IN nodes(p) | SET n.marked = true) # Neptune openCypher MATCH p=(start)-[*]->(finish) WHERE start.name = 'A' AND finish.name = 'D' UNWIND nodes(p) AS n SET n.marked = true

在 Neptune 中重寫 NEO4j APOC 程序

下面範例會使用 openCypher 來取代一些最常用的 APOC 程序。這些範例僅供參考,旨在提供一些有關如何處理常見案例的建議。實際上,每個應用程序都有所不同,您必須制定自己的策略來提供您需要的所有功能。

重寫 apoc.export 程序

Neptune 會使用 neptune-export 公用程式,為各種輸出格式 (例如 CSV 和 JSON) 的完整圖形和查詢型匯出提供一系列選項 (請參閱 從 Neptune 資料庫叢集匯出資料)。

重寫 apoc.schema 程序

Neptune 沒有明確定義的結構描述、索引或限制條件,因此不再需要許多 apoc.schema 程序。範例如下:

  • apoc.schema.assert

  • apoc.schema.node.constraintExists

  • apoc.schema.node.indexExists,

  • apoc.schema.relationship.constraintExists

  • apoc.schema.relationship.indexExists

  • apoc.schema.nodes

  • apoc.schema.relationships

Neptune OpenCypher 確實支援擷取的值與程序擷取的值類似,如下所示,但可能會在較大的圖形上遇到效能問題,因為這樣做需要掃描圖形的大部分才能返回答案。

# openCypher replacement for apoc.schema.properties.distinct MATCH (n:airport) RETURN DISTINCT n.runways
# openCypher replacement for apoc.schema.properties.distinctCount MATCH (n:airport) RETURN DISTINCT n.runways, count(n.runways)

apoc.do 程序的替代方案

這些程序是用來提供條件式查詢執行,很容易使用其他 OpenCypher 子句來實作。在 Neptune 中,至少有兩種方法可以實現類似的行為:

  • 一種方法是將 OpenCypher 的清單理解功能與 UNWIND 子句結合。

  • 另一種方法是在 Gremlin 中使用 choose() 和 coalesce() 步驟。

這些方法的範例如下所示。

apoc.do.when 的替代方案

# Neo4J Example MATCH (n:airport {region: 'US-AK'}) CALL apoc.do.when( n.runways>=3, 'SET n.is_large_airport=true RETURN n', 'SET n.is_large_airport=false RETURN n', {n:n} ) YIELD value WITH collect(value.n) as airports RETURN size([a in airports where a.is_large_airport]) as large_airport_count, size([a in airports where NOT a.is_large_airport]) as small_airport_count # Neptune openCypher MATCH (n:airport {region: 'US-AK'}) WITH n.region as region, collect(n) as airports WITH [a IN airports where a.runways >= 3] as large_airports, [a IN airports where a.runways < 3] as small_airports, airports UNWIND large_airports as la SET la.is_large_airport=true WITH DISTINCT small_airports, airports UNWIND small_airports as la SET la.small_airports=true WITH DISTINCT airports RETURN size([a in airports where a.is_large_airport]) as large_airport_count, size([a in airports where NOT a.is_large_airport]) as small_airport_count #Neptune Gremlin using choose() g.V(). has('airport', 'region', 'US-AK'). choose( values('runways').is(lt(3)), property(single, 'is_large_airport', false), property(single, 'is_large_airport', true)). fold(). project('large_airport_count', 'small_airport_count'). by(unfold().has('is_large_airport', true).count()). by(unfold().has('is_large_airport', false).count()) #Neptune Gremlin using coalesce() g.V(). has('airport', 'region', 'US-AK'). coalesce( where(values('runways').is(lt(3))). property(single, 'is_large_airport', false), property(single, 'is_large_airport', true)). fold(). project('large_airport_count', 'small_airport_count'). by(unfold().has('is_large_airport', true).count()). by(unfold().has('is_large_airport', false).count())

apoc.do.case 的替代方案

# Neo4J Example MATCH (n:airport {region: 'US-AK'}) CALL apoc.case([ n.runways=1, 'RETURN "Has one runway" as b', n.runways=2, 'RETURN "Has two runways" as b' ], 'RETURN "Has more than 2 runways" as b' ) YIELD value RETURN {type: value.b,airport: n} # Neptune openCypher MATCH (n:airport {region: 'US-AK'}) WITH n.region as region, collect(n) as airports WITH [a IN airports where a.runways =1] as single_runway, [a IN airports where a.runways =2] as double_runway, [a IN airports where a.runways >2] as many_runway UNWIND single_runway as sr WITH {type: "Has one runway",airport: sr} as res, double_runway, many_runway WITH DISTINCT double_runway as double_runway, collect(res) as res, many_runway UNWIND double_runway as dr WITH {type: "Has two runways",airport: dr} as two_runways, res, many_runway WITH collect(two_runways)+res as res, many_runway UNWIND many_runway as mr WITH {type: "Has more than 2 runways",airport: mr} as res2, res, many_runway WITH collect(res2)+res as res UNWIND res as r RETURN r #Neptune Gremlin using choose() g.V(). has('airport', 'region', 'US-AK'). project('type', 'airport'). by( choose(values('runways')). option(1, constant("Has one runway")). option(2, constant("Has two runways")). option(none, constant("Has more than 2 runways"))). by(elementMap()) #Neptune Gremlin using coalesce() g.V(). has('airport', 'region', 'US-AK'). project('type', 'airport'). by( coalesce( has('runways', 1).constant("Has one runway"), has('runways', 2).constant("Has two runways"), constant("Has more than 2 runways"))). by(elementMap())

清單型屬性的替代方案

Neptune 目前不支援儲存清單型屬性。不過,您可以將清單值儲存為逗號分隔字串,然後使用 join()split() 函數來建構和解構清單屬性,以取得類似的結果。

例如,如果想要將標籤清單儲存為屬性,則可以使用重寫範例,其中展示如何擷取逗號分隔屬性,然後使用 split()join() 函數搭配清單理解來實現可比較的結果:

# Neo4j Example (In this example, tags is a durable list of string. MATCH (person:person {name: "TeeMan"}) WITH person, [tag in person.tags WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags SET person.tags = newTags RETURN person # Neptune openCypher MATCH (person:person {name: "TeeMan"}) WITH person, [tag in split(person.tags, ',') WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags SET person.tags = join(newTags,',') RETURN person

重寫 CALL 子查詢

Neptune CALL子查詢不支援將變數匯入子查詢範圍CALL (friend) { ... }的語法 (在此範例中friend為 )。請針對相同的子查詢使用WITH子句,例如 。 CALL { WITH friend ... }

目前不支援選用CALL的子查詢。

Neptune openCypher 與 Cypher 之間的其他差異

  • Neptune 僅支援 Bolt 通訊協定的 TCP 連線。不支援 Bolt 的 WebSockets 連線。

  • Neptune openCypher 會移除 trim()ltrim()rtrim() 函數中由 Unicode 定義的空格。

  • 在 Neptune OpenCypher 中,tostring(double) 不會自動切換到 E 表示法,表示 double 的大值。

下一個主題:

遷移資源

上一個主題:

Neptune 相容性
隱私權網站條款Cookie 偏好設定
© 2025, Amazon Web Services, Inc.或其附屬公司。保留所有權利。