簡體   English   中英

Neo4j雙向遍歷API

[英]Neo4j bidirectional traversal api

我正在玩Neo4j,到目前為止,我有一個地理圖,其中AIRPORT連接到CITYCITY連接到COUNTRYCOUNTRYCONTINENT ,如圖所示 在此處輸入圖片說明

箭頭上的標簽將org.neo4j.graphdb.RelationshipType轉換為我的代碼。 到目前為止,我可以使用以下單向遍歷構建起始節點MXP到終止節點LTN之間的路徑。

Traverser traverse = database.traversalDescription().depthFirst()
  .relationships(CITY, BOTH)
  .relationships(CONTINENT, BOTH)
  .relationships(COUNTRY, BOTH)
  .relationships(REGION, BOTH)
  .evaluator(Evaluators.includeWhereEndNodeIs(endNode)).traverse(startNode);

這樣,我得到了一條單一路徑MXP -> Milan -> Italy -> Europe <- England <- London <- LTN ,這對於圖形描述,遍歷描述以及我對這種描述的理解當然是正確的。

我正在嘗試更改此代碼以執行雙向遍歷,這意味着我想同時從MXPLTN並在沖突點處停止。 我嘗試使用以下代碼段,其中的注釋表示我的理解,因此可能更容易指出問題。

TraversalDescription startSide = database.traversalDescription().depthFirst() //Depth first algorithm
  .relationships(CITY, OUTGOING) //consider CITY relationship, only outgoing
  .relationships(REGION, OUTGOING) //consider REGION relationship, only outgoing
  .relationships(COUNTRY, OUTGOING) //consider COUNTRY relationship, only outgoing
  .relationships(CONTINENT, OUTGOING) //consider CONTINENT relationship, only outgoing
  .evaluator(Evaluators.excludeStartPosition()); //do not consider the starting point. 
                                               //Here I tried also with all, with the same result
                                               //with includeWhereEndNodeIs(endNode), again with same result
                                               //and combining includeWhereEndNodeIs and excludeStartPosition, once more with same result.
                                               //All tries I mirrored for the endSide description, changing endNode to startNode where I feel it was needed

TraversalDescription endSide = database.traversalDescription().depthFirst()
  .relationships(CITY, OUTGOING)
  .relationships(REGION, OUTGOING)
  .relationships(COUNTRY, OUTGOING)
  .relationships(CONTINENT, OUTGOING)
  .evaluator(Evaluators.excludeStartPosition());

List<Node> asList = Arrays.asList(startNode, endNode);
Traverser traverse = database.bidirectionalTraversalDescription().endSide(endSide).startSide(startSide).traverse(asList, asList);

在這里,我得到了兩條路徑,而不是單向遍歷嘗試得到的路徑,一條只有MXP ,一條只有LTN

在這一點上,我深信我完全誤解了雙向遍歷,甚至可能是它的目的。 我的錯誤在哪里? 為什么我沒有得到相同的輸出?

我終於有了一個可行的解決方案。 我的代碼中的問題與唯一性的概念有關。 我的問題有趣的一點是

設置規則,以便在遍歷期間重新訪問位置,如“唯一性”中所述。 如果未設置,則默認為NODE_GLOBAL。

NODE_GLOBAL唯一性:整個圖形中的任何節點都不能被多次訪問。 這可能會消耗大量內存,因為它需要保持內存中的數據結構來記住所有訪問的節點。

NODE_PATH唯一性:節點可能不會在到達它的路徑中先前出現。

這些描述與官方API有所不同,因此我嘗試使用不同的組合,並得到以下代碼:

TraversalDescription bothSide = database.traversalDescription().depthFirst()
    .relationships(CITY, OUTGOING)
    .relationships(REGION, OUTGOING)
    .relationships(COUNTRY, OUTGOING)
    .relationships(CONTINENT, OUTGOING)
    .uniqueness(NODE_PATH);

Traverser traverser = database
    .bidirectionalTraversalDescription()
    .startSide(bothSide)
    .endSide(bothSide)
    .traverse(node, endNode);

基本上,我為末尾和起始端都定義了一個通用的TraversalDescription ,在這里我只想遵循傳出關系,並且我只想考慮路徑本身在節點內唯一的路徑。

然后,我定義了一個bidirectional traverser ,該bidirectional traverser器簡單地設置了端點和起始端,並從起始節點node到終止節點endNode遍歷了圖形(實際上,它從起點到終點以及從終點到起點同時遍歷並在兩個遍歷發生沖突時停止,從而將生成的路徑合並為從startend的單個路徑)。

注意 :我不確定NODE_GLOBAL的含義,因為在我的數據庫中,每個節點都代表一個地理實體,因此路徑MXP -> Milan -> Italy -> Europe <- England <- London <- LTN NODE_GLOBAL MXP -> Milan -> Italy -> Europe <- England <- London <- LTN NODE_GLOBAL只能被訪問一次,因此在這種情況下NODE_GLOBALNODE_PATH之間應該沒有區別。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM