JanusGraph 爲 PHP 助力

JanusGraph 爲 PHP 助力

隨着 JanusGraph 的日益流行,開發者們也毫無疑問地圍繞着它開發着相應的工具。在這篇來自 Compose Write Stuff 的文章中,Campus Discounts 的創始人兼首席技術官 Don Omondi 將談到他爲 JanusGraph 開發新的 PHP 庫而且分享如何使用它。php

在編程語言的世界中,PHP 並不須要過多介紹。它在 1995 年正式對外發布了 1.0 版本。如今 PHP 已經成爲許多獨角獸公司的中堅力量,而其中最爲人知曉的就是 Facebook,最近像 Slack 也加入了 PHP 的陣營。截至 2017 年 9 月,W3Techs 報告稱,在全部已知網站中,服務端編程語言使用了 PHP 的佔了 82.8% !前端

在數據庫的世界中,JanusGraph 雖是一位新成員,但它卻有着深厚的技術底蘊,由於它創建在開源圖形數據庫的前任領導者 Titan 的基礎上。爲了提供給您一些關於圖數據庫的背景知識,請看圖數據庫簡介。雖然 JanusGraph 還很年輕,可是它已經被一個知名的獨角獸公司 —— Uber 使用。android

因此最大的問題是,如何使用 PHP 和 JanusGraph 建立一家獨角獸公司?相信我,我也但願我知道答案!可是,若是問題是如何使用 JanusGraph 來強化 PHP ?我卻是知道不止一種方法。ios

Gremlin-OGM PHP 庫介紹

Gremlin-OGM PHP 庫是 Tinkerpop 3+ 兼容的圖形數據庫(JanusGraph,Neo4j 等)的對象圖形映射器,容許您保存數據並運行 gremlin 查詢。git

該庫已經託管在 Packagist 上了 ,因此能夠輕鬆的使用 Composer 安裝。github

composer require the-don-himself/gremlin-ogm  
複製代碼

使用該庫也很容易,由於它有大量的 PHP 註釋。可是在咱們開始使用它以前,讓咱們深刻探討一下使用像 JanusGraph 這樣的圖形數據庫時可能遇到的一些問題以及該庫如何幫助您避免它們。數據庫

注意事項

首先,具備相同名稱的全部屬性必須具備相同的數據類型。若是您已經在不一樣的數據庫中有數據,好比 MySQL 或者 MongoDB ,那麼您可能會遇到這種狀況。編程

一個很好的例子就是在每一個實體類或文檔中稱爲 id 的字段。一些 ID 多是一個整數的數據類型(一、二、3 等), 其餘一些多是字符串類型 (例如在常見問題解答庫中的 ID en_1es_1fr_1),另外還有好比 MongoDB 的 UUID(例子 59be8696540bbb198c0065c4)。對於這些不一樣的數據類型使用相同屬性名稱的狀況會引起異常。Gremlin-OGM 庫會發現這樣的衝突並拒絕執行。做爲一種解決方法,我建議將標籤與單詞 id 組合; 例如,用戶的標識符變爲 users_id 。該庫附帶一個序列化程序,容許您將字段映射到虛擬屬性以免此衝突。後端

其次,屬性(property)名稱,邊緣(edge)標籤和頂點(vertex)標籤在圖中必須都是惟一的。例如,將 Vertex 標記爲 tweets 並引用一個對象,而後建立一個 Edge 標記爲 tweets 並引用用戶操做,或者在 users Vertex 中建立一個 property tweets 來引用用戶發出的推文數量。該庫一樣會發現這種衝突並拒絕執行。api

第三,對於性能和模式的有效性,我建議確保每一個元素,或者至少每一個頂點包含一個惟一的屬性,在該惟一屬性上將建立惟一的組合索引(也稱爲鍵索引)。這確保全部元素都是惟一的,而且會提升性能,由於在頂點之間添加邊緣首先須要查詢它們是否先存在。該庫容許您爲此目的使用 @Id 註釋標記屬性。

最後,索引。這一點值得寫一本或兩本書。在 JanusGraph 中,基本上您索引的是屬性(畢竟它是一個屬性圖),可是能夠在不一樣的頂點和邊緣上使用相同的屬性名稱。這樣作時要很是當心。請記住第一件要注意的事情。所以,例如在默認狀況下,屬性 total_comments 上的索引將跨越全部頂點和邊緣。查詢其中total_comments 大於 5 的頂點會返回 total_comments > 5userstotal_comments > 5 的博客帖子以及知足該查詢的任何其餘頂點的混合狀況。更糟糕的狀況是,一段時間後,若是您在 recipes 頂點了加一個 total_comments 屬性,那麼你現有的查詢就會出錯了。

爲了防止上述潛在的問題,JanusGraph 容許您在建立索引時設置標籤參數以限制其範圍。我建議這樣作以保持索引更小和更高性能,但這意味着您必須爲每一個索引提供一個惟一的名稱。Gremlin-OGM 庫查找任何衝突的索引名稱,若是發現將拒絕執行。

如何使用 Gremlin-OGM

要開始使用 Gremlin-OGM ,咱們首先須要在咱們的源文件夾中建立一個名爲 Graph 的目錄,例如 src/Graph。在這個目錄下,咱們須要建立兩個不一樣的目錄:一個叫作 Vertices ,另外一個叫作 Edges 。這兩個目錄如今將包含定義咱們圖表元素的PHP類。

頂點文件夾中的每一個類主要使用註釋描述頂點標籤,關聯索引和屬性。對於更高級的用例,若是您使用 MongoDB 並擁有一個保存嵌入式文檔的類(例如註釋集合),則還能夠定義最適合的嵌入邊緣。

邊緣文件夾中的每一個類仍是經過註釋描述邊緣標籤,相關索引和屬性。每一個邊緣類中的兩個屬性也可使用註釋進行標記,一個用於描述頂點從哪連接過來的,另外一個用於描述頂點要連接去哪。它的使用真的很簡單,但咱們仍是用一個實例來講明吧。

一個實際的例子:推特

Twitter和圖形數據庫真的是天生一對。像用戶和推文這樣的對象能夠造成頂點,而諸如 follow ,likes ,tweeted 和 retweets 等操做能夠造成邊緣。請注意,邊緣 tweeted 是以這種方式命名的,以免與頂點 tweets 發生衝突。這個簡單的模型的圖形表示能夠以下圖所示。

讓咱們在 Graph/Vertexes 文件夾和 Graph/Edges 文件夾中建立相應的類。tweets 類可能以下所示:

<?php  
namespace TheDonHimself\GremlinOGM\TwitterGraph\Graph\Vertices;  
use JMS\Serializer\Annotation as Serializer;  
use TheDonHimself\GremlinOGM\Annotation as Graph;  
/**
* @Serializer\ExclusionPolicy("all")
* @Graph\Vertex(
* label="tweets",
* indexes={
* @Graph\Index(
* name="byTweetsIdComposite",
* type="Composite",
* unique=true,
* label_constraint=true,
* keys={
* "tweets_id"
* }
* ),
* @Graph\Index(
* name="tweetsMixed",
* type="Mixed",
* label_constraint=true,
* keys={
* "tweets_id" : "DEFAULT",
* "text" : "TEXT",
* "retweet_count" : "DEFAULT",
* "created_at" : "DEFAULT",
* "favorited" : "DEFAULT",
* "retweeted" : "DEFAULT",
* "source" : "STRING"
* }
* )
* }
* )
*/
class Tweets  
{
 /**
 * @Serializer\Type("integer")
 * @Serializer\Expose
 * @Serializer\Groups({"Default"})
 */
 public $id;
 /**
 * @Serializer\VirtualProperty
 * @Serializer\Expose
 * @Serializer\Type("integer")
 * @Serializer\Groups({"Graph"})
 * @Serializer\SerializedName("tweets_id")
 * @Graph\Id
 * @Graph\PropertyName("tweets_id")
 * @Graph\PropertyType("Long")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public function getVirtualId()
 {
 return self::getId();
 }
 /**
 * @Serializer\Type("string")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("text")
 * @Graph\PropertyType("String")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $text;
 /**
 * @Serializer\Type("integer")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("retweet_count")
 * @Graph\PropertyType("Integer")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $retweet_count;
 /**
 * @Serializer\Type("boolean")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("favorited")
 * @Graph\PropertyType("Boolean")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $favorited;
 /**
 * @Serializer\Type("boolean")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("retweeted")
 * @Graph\PropertyType("Boolean")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $retweeted;
 /**
 * @Serializer\Type("DateTime<'', '', 'D M d H:i:s P Y'>")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("created_at")
 * @Graph\PropertyType("Date")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $created_at;
 /**
 * @Serializer\Type("string")
 * @Serializer\Expose
 * @Serializer\Groups({"Default", "Graph"})
 * @Graph\PropertyName("source")
 * @Graph\PropertyType("String")
 * @Graph\PropertyCardinality("SINGLE")
 */
 public $source;
 /**
 * @Serializer\Type("TheDonHimself\GremlinOGM\TwitterGraph\Graph\Vertices\Users")
 * @Serializer\Expose
 * @Serializer\Groups({"Default"})
 */
 public $user;
 /**
 * @Serializer\Type("TheDonHimself\GremlinOGM\TwitterGraph\Graph\Vertices\Tweets")
 * @Serializer\Expose
 * @Serializer\Groups({"Default"})
 */
 public $retweeted_status;
 /**
 * Get id.
 *
 * @return int
 */
 public function getId()
 {
 return $this->id;
 }
}
複製代碼

Twitter API 很是具備表現力,儘管咱們實際上能夠保存比頂點類容許的多得多的數據。可是,對於這個示例,咱們只是對幾個屬性感興趣。上述註釋將告訴序列化程序僅在將 Twitter API 數據反序列化爲頂點類對象時填充這些字段。

users 頂點建立一個相似的類。完整的示例代碼位於庫中的 TwitterGraph 文件夾中。

在 Graph/Edges 文件夾中能夠建立一個示例 Follows 邊緣類,它看起來像這樣:

<?php  
namespace TheDonHimself\GremlinOGM\TwitterGraph\Graph\Edges;  
use JMS\Serializer\Annotation as Serializer;  
use TheDonHimself\GremlinOGM\Annotation as Graph;  
/**
* @Serializer\ExclusionPolicy("all")
* @Graph\Edge(
* label="follows",
* multiplicity="MULTI"
* )
*/
class Follows  
{
 /**
 * @Graph\AddEdgeFromVertex(
 * targetVertex="users",
 * uniquePropertyKey="users_id",
 * methodsForKeyValue={"getUserVertex1Id"}
 * )
 */
 protected $userVertex1Id;
 /**
 * @Graph\AddEdgeToVertex(
 * targetVertex="users",
 * uniquePropertyKey="users_id",
 * methodsForKeyValue={"getUserVertex2Id"}
 * )
 */
 protected $userVertex2Id;
 public function __construct($user1_vertex_id, $user2_vertex_id)
 {
 $this->userVertex1Id = $user1_vertex_id;
 $this->userVertex2Id = $user2_vertex_id;
 }
 /**
 * Get User 1 Vertex ID.
 *
 *
 * @return int
 */
 public function getUserVertex1Id()
 {
 return $this->userVertex1Id;
 }
 /**
 * Get User 2 Vertex ID.
 *
 *
 * @return int
 */
 public function getUserVertex2Id()
 {
 return $this->userVertex2Id;
 }
}
複製代碼

likestweetedretweets 邊緣建立相似的類。完成後,咱們能夠經過運行如下命令來檢查模型的有效性:

php bin/graph twittergraph:schema:check  
複製代碼

若是拋出異常,那麼咱們須要先解決它們;不然,咱們的模型已經設置好了,如今咱們須要作的就是告訴 JanusGraph 。

JanusGraph 鏈接

TheDonHimself\GremlinOGM\GraphConnection 類負責初始化圖形鏈接。您能夠經過建立一個新的實例並在數組中傳遞一些鏈接選項來實現。

$options = [
 'host' => 127.0.0.1,
 'port' => 8182,
 'username' => null,
 'password' => null,
 'ssl' = [
 'ssl_verify_peer' => false,
 'ssl_verify_peer_name' => false
 ],
 'graph' => 'graph',
 'timeout' => 10,
 'emptySet' => true,
 'retryAttempts' => 3,
 'vendor' = [
 'name' => _self', 'database' => 'janusgraph', 'version' => '0.2' ], 'twitter' => [ 'consumer_key' => 'LnUQzlkWlNT4oNUh7a2rwFtwe', 'consumer_secret' => 'WCIu0YhaOUBPq11lj8psxZYobCjXpYXHxXA6rVcqbuNDYXEoP0', 'access_token' => '622225192-upvfXMpeb9a3FMhuid6oBiCRsiAokpNFgbVeeRxl', 'access_token_secret' => '9M5MnJOns2AFeZbdTeSk3R81ZVjltJCXKtxUav1MgsN7Z' ] ]; 複製代碼

vendor 數組能夠指定 vendor-specific 信息,如 gremlin 兼容的數據庫、版本、服務主機名稱(或 _self 本機)以及圖的名稱。

最終建立模型,咱們將運行此命令。

php bin/graph twittergraph:schema:create  
複製代碼

這個命令將要求一個可選的 configPath 參數,該參數是創建鏈接時包含 options 數組的 yaml 配置文件的位置。該庫在根文件夾中有三個示例配置,janusgraph.yamljanusgraphcompose.yamlazure-cosmosdb.yaml

上述命令將遞歸遍歷咱們的 TwitterGraph/Graph 目錄並查找全部 @Graph 註釋來構建模型定義。若是發現異常將被拋出;不然,它將啓動一個 Graph 事務來一次提交全部屬性、邊緣和頂點,或者在失敗時回滾。

一樣的命令也會詢問您是否要執行 dry run。若是指定,則不會將命令發送到 gremlin 服務器,而是將其轉儲到您能夠檢查的 command.groovy 文件中。對於Twitter示例,這 26 行是根據您的配置發送或轉儲的命令(如janusgraph _self 本機)。

mgmt = graph.openManagement()  
text = mgmt.makePropertyKey('text').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
retweet_count = mgmt.makePropertyKey('retweet_count').dataType(Integer.class).cardinality(Cardinality.SINGLE).make()  
retweeted = mgmt.makePropertyKey('retweeted').dataType(Boolean.class).cardinality(Cardinality.SINGLE).make()  
created_at = mgmt.makePropertyKey('created_at').dataType(Date.class).cardinality(Cardinality.SINGLE).make()  
source = mgmt.makePropertyKey('source').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
tweets_id = mgmt.makePropertyKey('tweets_id').dataType(Long.class).cardinality(Cardinality.SINGLE).make()  
name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
screen_name = mgmt.makePropertyKey('screen_name').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
description = mgmt.makePropertyKey('description').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
followers_count = mgmt.makePropertyKey('followers_count').dataType(Integer.class).cardinality(Cardinality.SINGLE).make()  
verified = mgmt.makePropertyKey('verified').dataType(Boolean.class).cardinality(Cardinality.SINGLE).make()  
lang = mgmt.makePropertyKey('lang').dataType(String.class).cardinality(Cardinality.SINGLE).make()  
users_id = mgmt.makePropertyKey('users_id').dataType(Long.class).cardinality(Cardinality.SINGLE).make()  
tweets = mgmt.makeVertexLabel('tweets').make()  
users = mgmt.makeVertexLabel('users').make()  
follows = mgmt.makeEdgeLabel('follows').multiplicity(MULTI).make()  
likes = mgmt.makeEdgeLabel('likes').multiplicity(MULTI).make()  
retweets = mgmt.makeEdgeLabel('retweets').multiplicity(MULTI).make()  
tweeted = mgmt.makeEdgeLabel('tweeted').multiplicity(ONE2MANY).make()  
mgmt.buildIndex('byTweetsIdComposite', Vertex.class).addKey(tweets_id).unique().indexOnly(tweets).buildCompositeIndex()  
mgmt.buildIndex('tweetsMixed',Vertex.class).addKey(tweets_id).addKey(text,Mapping.TEXT.asParameter()).addKey(retweet_count).addKey(created_at).addKey(retweeted).addKey(source,Mapping.STRING.asParameter()).indexOnly(tweets).buildMixedIndex("search")  
mgmt.buildIndex('byUsersIdComposite',Vertex.class).addKey(users_id).unique().indexOnly(users).buildCompositeIndex()  
mgmt.buildIndex('byScreenNameComposite',Vertex.class).addKey(screen_name).unique().indexOnly(users).buildCompositeIndex()  
mgmt.buildIndex('usersMixed',Vertex.class).addKey(users_id).addKey(name,Mapping.TEXTSTRING.asParameter()).addKey(screen_name,Mapping.STRING.asParameter()).addKey(description,Mapping.TEXT.asParameter()).addKey(followers_count).addKey(created_at).addKey(verified).addKey(lang,Mapping.STRING.asParameter()).indexOnly(users).buildMixedIndex("search")  
mgmt.commit()  
複製代碼

如今咱們有了一個有效的模型設置,咱們須要的只是數據。Twitter API 有很好的文檔關於如何請求這些數據。Gremlin-OGM 庫附帶了一個 twitteroauth 包 (abraham/twitteroauth) 以及一個準備好的只讀 Twitter 應用程序,用於測試該庫並幫助您開始使用。

從 API 中獲取數據後,保持頂點很是簡單。首先,將 JSON 反序列化爲相應的頂點類對象。所以,例如,@TwitterDev 經過取回的 Twitter 數據 /api/users/show 將被反序列化,如圖所示 var_dump()

object(TheDonHimself\GremlinOGM\TwitterGraph\Graph\Vertices\Users)#432 (8) { 
 ["id"]=>
 int(2244994945)
 ["name"]=>
 string(10) "TwitterDev"
 ["screen_name"]=>
 string(10) "TwitterDev"
 ["description"]=>
 string(136) "Developer and Platform Relations @Twitter. We are developer advocates. We can't answer all your questions, but we listen to all of them!"  
 ["followers_count"]=>
 int(429831)
 ["created_at"]=>
 object(DateTime)#445 (3) {
 ["date"]=>
 string(26) "2013-12-14 04:35:55.000000"
 ["timezone_type"]=>
 int(1)
 ["timezone"]=>
 string(6) "+00:00"
 }
 ["verified"]=>
 bool(true)
 ["lang"]=>
 string(2) "en"
}
複製代碼

序列化的 PHP 對象如今已經開始在各自的頂點和邊緣中造成。可是,咱們只能將 gremlin 命令做爲字符串發送,因此咱們仍然須要將對象序列化爲命令字符串。咱們將使用一個方便命名的類GraphSerializer 來執行此操做。將反序列化的對象傳遞給GraphSerializer 的一個實例,該實例將處理複雜的序列化,如剝離新行,添加斜槓,將PHP DateTime 轉換爲 JanusGraph 所指望的格式。GraphSerializer 也優雅地處理 Geopoint 和 Geoshape 序列化。

// Get Default Serializer
$serializer = SerializerBuilder::create()->build();
// Get Twitter User
$decoded_user = $connection->get(
 'users/show',
 array(
 'screen_name' => $twitter_handle,
 'include_entities' => false,
 )
);
if (404 == $connection->getLastHttpCode()) {  
 $output->writeln('Twitter User @'.$twitter_handle.' Does Not Exist');
 return;
}
// Use default serializer to convert array from Twitter API to Users Class Object handling complex
deserialization like Date Time  
$user = $serializer->fromArray($decoded_user, Users::class);
// Initiate Special Graph Serializer
$graph_serializer = new GraphSerializer();
// Use graph serializer to convert Users Class Object to array handling complex deserialization like
Geoshape  
$user_array = $graph_serializer->toArray($user);
// Use graph serializer to convert array to a gremlin command string ready to be sent over
$command = $graph_serializer->toVertex($user_array);
複製代碼

GraphSerializer 輸出將串入 Gremlin 的命令。這個字符串就準備好發送到 JanusGraph 服務器。因此在上面的例子中,它變成:

"g.addV(label, 'users', 'users_id', 2244994945, 'name', 'TwitterDev', 'screen_name', 'TwitterDev', 'description', 'Developer and Platform Relations @Twitter. We are developer advocates. We can\'t answer all your questions, but we listen to all of them!', 'followers_count', 429831, 'created_at', 1386995755000, 'verified', true, 'lang', 'en')"
複製代碼

保存邊緣要稍微簡單一點,由於它的前提是定點存在。所以,庫須要知道屬性鍵值對來查找它們。此外,邊緣在圖數據庫中具備方向和多重性。所以,邊緣要添加到頂點這很是重要。

這是 Edge 類中 @Graph\AddEdgeFromVertex@Graph\AddEdgeToVertex 屬性註釋的用途。它們都擴展了 @Graph\AddEdge 註解來指示目標頂點類以及屬性鍵和獲取該值所需的方法數組。

假設咱們已經在 Twitter API 中查詢到了 tweets ,其中包含一個名爲 user 的嵌入字段,用於保存 tweeter 數據。若是 users_id:5 建立了 tweets_id:7 ,則序列化的 gremlin 命令將以下所示:

if (g.V().hasLabel('users').has('users_id',5).hasNext() == true  
   && g.V().hasLabel('tweets').has('tweets_id',7).hasNext() == true) 
     { 
       g.V().hasLabel('users').has('users_id',5).next().addEdge('tweeted', 
         g.V().hasLabel('tweets').has('tweets_id',7).next()) 
     }
複製代碼

所以,兩個頂點查詢是一個事務,而後在userstweets 之間建立兩條邊緣。請注意,由於一個用戶能夠屢次發 tweet ,但每一個 tweet 只能有一個擁有者,因此其重複性爲 ONE2MANY

若是邊緣類具備像 tweeted_ontweeted_from 這樣的屬性,那麼庫就會像頂點同樣適當地序列化它們。

JanusGraph 查詢

咱們處理了抓取和保存的數據。數據查詢也是庫幫助完成的。TheDonHimself\Traversal\TraversalBuilder 類提供了幾乎與 gremlin 完美匹配的本地API。例如,在 TwitterGraph 中獲取用戶能夠實現以下。

$user_id = 12345;
$traversalBuilder = new TraversalBuilder();
$command = $traversalBuilder
 ->g()
 ->V()
 ->hasLabel("'users'")
 ->has("'users_id'", "$user_id")
 ->getTraversal();
複製代碼

獲取用戶時間線這樣稍微複雜的例子能夠經過如下方式實現。

$command = $traversalBuilder
 ->g()
 ->V()
 ->hasLabel("'users'")
 ->has("'screen_name'", "'$screen_name'")
 ->union(
 (new TraversalBuilder())->out("'tweeted'")->getTraversal(),
 (new TraversalBuilder())->out("'follows'")->out("'tweeted'")->getTraversal()
 )
 ->order()
 ->by("'created_at'", 'decr')
 ->limit(10)
 ->getTraversal();
複製代碼

詳細步驟能夠在 \TheDonHimself\Traversal\Step 類中找到.

GraphQL 到 Gremlin

有一個獨立的嘗試 來建立一種支持 GraphQL to Gremlin 命令的標準。它處於早期階段,只支持查詢而不支持變動。既然它也是我寫的,Gremlin-OGM 庫固然也支持這個標準,但願隨着時間的推移會有所改進。

JanusGraph 可視化

可悲的是,它沒有像關係數據庫,文檔數據庫和鍵值數據庫那樣多的 Graph Database GUI。其中Gephi,可用於經過流式插件來可視化 JanusGraph 數據和查詢。與此同時,撰寫有 JanusGraph 的數據瀏覽器,可使用它來顯示 TwitterGraph 的一些查詢。

將我關注的 5 位用戶可視化

def graph = ConfiguredGraphFactory.open("twitter");  
def g = graph.traversal();  
g.V().hasLabel('users').has('screen_name',  
   textRegex('(i)the_don_himself')).outE('follows').limit(5).inV().path()
複製代碼

可視化 5 位關注個人用戶

def graph = ConfiguredGraphFactory.open("twitter");  
def g = graph.traversal();  
g.V().hasLabel('users').has('screen_name',  
    textRegex('(i)the_don_himself')).inE('follows').limit(5).outV().path()
複製代碼

可視化我喜歡的 5 條推文

def graph = ConfiguredGraphFactory.open("twitter");  
def g = graph.traversal();  
g.V().hasLabel('users').has('screen_name',  
    textRegex('(?i)the_don_himself')).outE('likes').limit(5).inV().path()
複製代碼

可視化任意 5 條轉推以及原推

def graph = ConfiguredGraphFactory.open("twitter");  
def g = graph.traversal();  
g.V().hasLabel('tweets').outE('retweets').inV().limit(5).path()  
複製代碼

如今您擁有了它。一個功能強大、考慮周到、操做簡單的庫,它可幫助您在幾分鐘內開始使用 PHP 操做 JanusGraph 。若是您使用了使人驚歎的 Symfony 框架,那麼您的運氣會更好。即將發行的軟件包 Gremlin-OGM-Bundle 將幫助您將數據從 RDBMS 或 MongoDB 複製到 Tinkerpop 3+ 兼容圖形數據庫中。請享用!


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索