JanusGraph 為 PHP 助力

GanymedeNil發表於2018-04-03

JanusGraph 為 PHP 助力

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

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

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

所以最大的問題是,如何使用 PHP 和 JanusGraph 建立一家獨角獸公司?相信我,我也希望我知道答案!但是,如果問題是如何使用 JanusGraph 來強化 PHP ?我倒是知道不止一種方法。

Gremlin-OGM PHP 庫介紹

Gremlin-OGM PHP 庫是 Tinkerpop 3+ 相容的圖形資料庫(JanusGraph,Neo4j 等)的物件圖形對映器,允許您儲存資料並執行 gremlin 查詢。

該庫已經託管在 Packagist 上了 ,所以可以輕鬆的使用 Composer 安裝。

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

使用該庫也很容易,因為它有大量的 PHP 註釋。但是在我們開始使用它之前,讓我們深入探討一下使用像 JanusGraph 這樣的圖形資料庫時可能遇到的一些問題以及該庫如何幫助您避免它們。

注意事項

首先,具有相同名稱的所有屬性必須具有相同的資料型別。如果您已經在不同的資料庫中有資料,比如 MySQL 或者 MongoDB ,那麼您可能會遇到這種情況。

一個很好的例子就是在每個實體類或文件中稱為 id 的欄位。一些 ID 可能是一個整數的資料型別(1、2、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 來引用使用者發出的推文數量。該庫同樣會發現這種衝突並拒絕執行。

第三,對於效能和模式的有效性,我建議確保每個元素,或者至少每個頂點包含一個唯一的屬性,在該唯一屬性上將建立唯一的組合索引(也稱為鍵索引)。這確保所有元素都是唯一的,並且會提高效能,因為在頂點之間新增邊緣首先需要查詢它們是否先存在。該庫允許您為此目的使用 @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 發生衝突。這個簡單的模型的圖形表示可以如下圖所示。

JanusGraph 為 PHP 助力

讓我們在 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()
複製程式碼

JanusGraph 為 PHP 助力

視覺化 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()
複製程式碼

JanusGraph 為 PHP 助力

視覺化我喜歡的 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()
複製程式碼

JanusGraph 為 PHP 助力

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

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

JanusGraph 為 PHP 助力

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


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

相關文章