雖然是演示圖形數據庫功能的最常見用例之一,但我似乎無法找到一個使用OrientDB SQL獲取「朋友的朋友」的好例子或最佳做法。使用OrientDB查找「朋友的朋友」SQL
讓我們假設一個社交網絡,並嘗試用「用戶」頂點和「is_friend_with」邊緣對它進行建模。
定義:
頂點類用戶與財產狀態性能UUID(自定義唯一ID)和名
邊緣種類is_friend_with從而可以成爲「」「或」覈准「
用戶用單向邊緣相互連接。方向並不重要;只要status =「approved」,那兩個用戶就是朋友。
這是我想出了一個解決辦法:
select from (
select expand($all) let
$a = (select expand(outE('is_friend_with')[status='approved'].inV('user').outE('is_friend_with')[status='approved'].inV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
$b = (select expand(outE('is_friend_with')[status='approved'].inV('user').inE('is_friend_with')[status='approved'].outV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
$c = (select expand(inE('is_friend_with')[status='approved'].outV('user').inE('is_friend_with')[status='approved'].outV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
$d = (select expand(inE('is_friend_with')[status='approved'].outV('user').outE('is_friend_with')[status='approved'].inV('user')) from (select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24')),
$all = unionall($a, $b, $c, $d)
) where uuid <> '95920a96a60c4d40a8f70bde98ae1a24'
(該以uuid用戶= '95920a96a60c4d40a8f70bde98ae1a24' 的出發點。)
但是,我並不覺得十分優雅。我可以立即發現的一些問題是:
- 重複
select from user where uuid = '95920a96a60c4d40a8f70bde98ae1a24'
。不幸的是,我找不到一種方法將它分配給一個變量,然後在「from」子句中使用它 - 我不得不使用both(),因爲我要檢查每一個邊緣的
status="approved"
- 此查詢還返回直接的朋友,而不是朋友的朋友只有
我試圖用移動,但無濟於事(同樣,沒有發現一種方法如何在遍歷時檢查邊緣的status="approved"
)。
請問您能爲這個問題提出一些OSQL解決方案嗎?提前致謝。
感謝您的回答,@ codemix。它工作正常,比我的解決方案更優雅。但是,查詢還會返回我們不感興趣的直接朋友(我通過執行創建邊緣IsFriendsWith(從用戶選擇uuid =「2」)(從用戶選擇uuid =「6」)來嘗試此操作。設置狀態=「批准」)。你可能有一個想法如何篩選出直接的朋友,並只返回建議的朋友(朋友的朋友)? – Bart 2015-02-24 12:35:10
@Zlatko查看我對我的答案所做的修改。 – codemix 2015-02-24 14:05:28
我沒有嘗試,但現在看起來不錯。由於我想遠離@rid,我想我會用'select from uuid =「xxx」'來重寫查詢。雖然會有重複,但索引會受到影響,所以這不會成爲問題。 (你可能知道如何將** select **分配給一個變量,並在**子句的某些**中重用它,如果可能的話)。非常感謝,@ codemix,我會接受這個答案。 – Bart 2015-02-24 14:30:41