ArangoDB 的graph查詢


一個graph包含vertices 和edges。edges被存儲在edges document當中。vertices可以是document collection 中的document也可以是edge document中的document。所以說edges也可以被當做vertices來使用。

1、數據准備

使用arangoimp導入飛機場和航班csv數據信息。

導入飛機場信息

arangoimp --file <em>path to airports.csv</em> on your machine --collection
airports --create-collection true --type csv  

  

這里我們創建了一個document collection;為每一行創建一個document.標題被作為屬性名稱。其中標題中包含一個_key的值,系統將自動識別該列作為_key.

現在打開瀏覽器(http://localhost:8529)便可以看到剛剛導入的信息了。

可以點擊瀏覽器中的queries進行查詢:

查詢所有的機場

FOR airport in ariports
RETURN airport

  

  僅查詢加利福尼亞機場信息

FOR airport IN airports
FILTER airport.state==‘CA’
RETURN airport

  

  查詢每個州擁有的機場數量

FOR airport IN airports
COLLECT state = airport.state
WITH COUNT ON counter
RETURN {state,counter}

  

  導入航班信息

arangoimp --file <em>path to flights.csv</em> on your machine --collection
flights --create-collection true --type csv --create-collection-type
edge

  

  這里創建的是edge collection,為每一行創建一個edge,同時自動創建一個edge index方便快速查詢(_from和_to組成了這樣的index.).在csv中有兩個特殊的列_from 和_to,它們的值為airports collection中的id,指明了從一個機場飛往另外一個機場。

2、graph數據查詢

語法

FOR Vertex,Edge,Path IN [min..max ] [OUTBAND|INBOUND|ANY] startvertex EDGECOLLECTION 

 

分析:

FOR 遍歷三個變量,分別是點(vertex)、關聯(edge),點和關系組成的路線(path) 

IN 在哪個EDGE COLLECTION中

[min..max]遍歷的最小深度、最大深度或者遍歷的深度范圍

OUTBOUND:從startvertex原始斷點開始向外查詢,即from 為startvertex;INBOUND為向內查詢,即to為startvertex,any:兩個方向全部查詢

startvertex:開始查詢的斷點

EDGE COLLECTION 遍歷的collection,可以是一個或多個edge collection

查詢示例:

查所洛杉磯可以直達的所有飛機場

FOR airport IN
OUTBOUND 'airports/LAX'
flights
RETURN DISTICT airport

  

  

返回10個從洛杉磯可以到達的飛機場及其航班。

FOR ariport flight IN
OUTBOUND 'airports/LAX'
LIMIT 10
flights
RETURN {airpot,flight}

  

  

3、查詢選項

(1)遍歷深度優先還是廣度優先

所有遍歷查詢默認是深度優先,深度優先和廣度優先都會返回相同的結果。但計算性能有時會相差很大。

如果要得到所有的節點,那么深度優先和廣度優先效率一樣。因為都要跑完所有的節點。

如果要是有篩選filter或者限制(limit)導致不完全篩選,那廣度優先可能會有更高的效率。

廣度優先示例:

FOR v IN 1..10 OUTBOUND 'vertical/s' edgs<br>OPTIONS {bfs:true}
FILTER v._key=='F'
LIMIT 1
RETURN v

  

  

(2)唯一遍歷

由於不同點之間的路徑可能有多條,也可能存在閉環線路

默認情況下,遍歷的時候如果path中遇到了相同的edge就會停止遍歷;這將可以防止遍歷存在繞圈情況,讓遍歷可以到達最底層節點。

在一個path上可能會出現重復的vertex,除非你明確聲明不要重復的點。

示例

FOR v,e,p IN 1..5 OUTBOUND 'vertex/s' edgs
OPTIONS {
uniqueVertices:'none',
uniqueEdges:'path'
}
RETURN CONCAT_SEPARATOR('->',p.vertices[*]._key)

  

  這個uniqueVertices:‘none’和uniqueEdges:‘path’都是默認設置,不設置也是一樣。這樣最開是的節點也可以是最后的節點,因為我們在設置的時候並沒有要求path中有唯一的點。如果要設置為唯一的,可以也設置為‘path’,這樣一條路徑中的點也將變為唯一的。

global保證每個點在所有遍歷中只出現一次。它僅適用於廣度優先。示例

FOR v IN 1..5  OUTBOUND 'vertex/s' edgs
OPTIONS{
bfs:ture,
uniqueVertices:'global'
RETURN v._key

  

  

從洛杉磯可以直達的機場

FOR ariport IN OUTBOUND 'airports/LAX' flights
OPTIONS {
bfs:true,
uniqueVertices:'global'}
RETURN airport

  

  這個查詢將比上面的使用distict快很多。因為distict是在遍歷完所有節點后再去除重復的,而options則可以直接過掉重復的結果不進行遍歷。

4、LET關鍵字

LET可以用來聲明變量,來將查詢結果賦值給變量。

FOR f IN flights
 FILTER f._from == 'airports/BIS'
 LIMIT 100
 LET h = FLOOR(f.DepTime / 100)
 LET m = f.DepTime % 100
 RETURN {
     year: f.Year,
     month: f.Month,
     day: f.DayofMonth,
     time: f.DepTime,
     iso: DATE_ISO8601(f.Year, f.Month, f.DayofMonth, h, m)
 }

  

  

5、shortest_path最短路徑

找到BIS 和JFK之間的最短路徑

FOR v IN OUTBOUND
SHORTEST_PATH 'airports/BIS'
TO 'airports/JFK'  flights
RETURN v

  

  注意,最短路徑只是找到一條路徑進行返回,其實可能還有其他的可能性。

LET airports = (
 FOR v IN OUTBOUND
 SHORTEST_PATH 'airports/BIS'
 TO 'airports/JFK' flights
 RETURN v
)
RETURN LENGTH(airports) - 1

  

  找到最少需要經過的機場,-1代表不包括最后一個節點。

在SHORTEST_PATH中不能使用filter只能使用pattern  matching代替。

6、pattern matching

問題:找到BIS 和 JFK之間最短的旅行時間。

第一步:找到BIS和JFK之間的最短路徑,我們已經知道最短路徑為2.

FOR v,e,p IN 2 OUTBOUND 'airports/BIS' flights
FILTER v.id='airports/JFK'
LIMIT 5
RETURN p

 

  

第二步:我們確定在同一天內,假設都為1月1日。

FOR v,e,p IN 2 OUTBOUND 'airports/BIS' flights
FILTER v._id='airports/JFK'
FILTER p.edges[*].month all == 1
FILTER p.edges[*].DayOfMonth all == 1
LIMIT 5
RETURN p

  

  數組之間的比較可以使用all,any ,none來表示。

第三步:計算每條path的飛行時間,並按照升序排列,這里使用DATE.DIFF()來計算

FOR v,e,p IN 2 OUTBOUND 'airports/BIS' flights
FILTER v._id='airports/JFK'
FILTER p.edges[*].month.all == 1
FILTER p.edges[*].DayofMonth all == 1
LET flightTime = DATE_DIFF(p.edges[0].DepTimeUTC-p.edges[1].ArrTimeUTC,'i')
SORT filghtTIme ASC
LIMIT 5
RETURN {flight:p,time:flightTime}

  

  

第四步:確定讓中轉時候的到達時間小於離開時間20分鍾

  

FOR v, e, p IN 2 OUTBOUND 'airports/BIS' flights
 FILTER v._id == 'airports/JFK'
 FILTER p.edges[*].Month ALL == 1
 FILTER p.edges[*].DayofMonth ALL == 1
 FILTER DATE_ADD(p.edges[0].ArrTimeUTC, 20, 'minutes') < p.edges[1].DepTimeUTC
 LET flightTime = DATE_DIFF(p.edges[0].DepTimeUTC, p.edges[1].ArrTimeUTC, 'i')
 SORT flightTime ASC
 LIMIT 5
 RETURN { flight: p, time: flightTime }

 

使用index進行優化

建立一個點中心索引,以_from,Month,DayOfMonth三個為聯合索引字段。即將FILTER的三個字段作為索引字段。

如果不以三個為聯合索引,那么系統將自動從首先篩選_from,其次遍歷month,其次遍歷_day,有了聯合索引直接就會找到‘airports/jfk’,month=1,dayofmonth=1,只用一次遍歷即可完成。因此聯合索引大大提高了遍歷的效率。

 

本文章轉載於博客園-ArangoDB 學習筆記 (4)graph 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM