kwattro / gh4j
使用Neo4j进行GitHub仓库分叉分析
Requires
- neoxygen/neoclient: ~2.0@dev
- symfony/finder: *
Requires (Dev)
- monolog/monolog: ~1.3
- phpunit/phpunit: 4.1.*
This package is not auto-updated.
Last update: 2024-09-10 07:25:29 UTC
README
轻松将GitHub事件数据归档导入Neo4j图数据库
免责声明!
由于事件负载完全不同,该工具不兼容GitHub ReST API。不过,它可以作为一个沙盒,以便将来切换到API。
是什么?
这是一个简单的库,可以解析GitHub事件归档文件并将这些事件加载到Neo4j图数据库中。
它包含一个简单的数据加载入口点和一些EventType
加载器,这些加载器将生成插入数据所需的Cypher查询。此库与一个简单的连接库耦合,以访问Neo4j ReST API。
它还会创建事件、仓库、用户、分叉和评论之间的关系,以便您可以全面了解GitHub上发生的事情以及它们是如何相关的。
注意/Achtung/Ola
此库主要作为一个个人实验制作,查询将生成的数据库模式适合于我打算处理数据的方式,我并不声称这是最佳模式,但它是与Neo4j图数据库玩耍的良好练习。
当然,建议、观点、PR等总是受欢迎的。
NB:提醒一下,GitHub上每小时大约有8000个事件
如何使用
1. 在您的项目依赖关系中要求Gh4j
库
将以下要求添加到您的composer.json
文件中
"require":{ // ..... other dependencies "kwattro/gh4j" : "dev-master" }
2. 实例化Gh4j
类
require 'vendor/autoload.php'; use Kwattro\Gh4j\Gh4j; $gh = new Gh4j();
下载GitHub事件数据归档
您可以在GitHub归档网站上下载数据归档。只需遵循说明,下载您想要期间的数据。
在您的计算机上某处解压缩下载的文件。
4. 将数据加载到数据库中
下载文件不是有效的JSON,但包含表示Event
发生的有效JSON的行。
使用PHP的file
函数,您将获得一个数组格式,其中每行包含JSON事件对象,循环遍历数组并加载事件。
$events = file('/Users/kwattro/gh/data/2014-06-01-3.json', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($events as $event) { $gh->loadEvent($event); }
然后,Gh4j
库将检查JSON的有效性,加载适当的EventType
加载器并将数据插入数据库。
默认情况下,每次调用loadEvent()
将触发与数据库的连接以插入数据。您可以使用Stack
方法累积*数量的查询,并在达到指定限制时刷新。
要使用它,您需要通过提供true
作为第二个参数来指示加载方法使用stackMethod。
// Code to read your file .... foreach ($events as $event) { $gh->loadEvent($event, true); } // Don't forget to flush after the loop to insert remaining queued queries $gh->flush();
这将累积查询,直到达到限制,然后发送一个大的查询。以50为限制,这比每次调用数据库快2倍,对于包含大约8000个事件的文件,在50秒内插入(1小时文件)。
您可以通过访问数据库连接器来调整stack
的限制。
$gh = new Gh4j(): $conn = $gh->getConnector(); $conn->setStackFlushLimit(30); // Stack will be flushed after 30 queries
支持的事件类型
目前有4种事件类型被处理
- PushEvent
- PullRequestEvent
- ForkEvent
- IssueCommentEvent
每种类型都将由一个自定义事件加载器处理,该加载器扩展了BaseEventLoader,该加载器为事件的常见负载创建Cypher查询。
建议您查看EventLoader目录内的代码注释,以了解数据如何插入,或者查看本README文件的“生成的Cypher查询”部分。
如果在数据中遇到不支持的EventType,它将被跳过。
更多内容即将到来...
生成的Cypher查询示例
PushEvent
MERGE (u:User {name:'ZhukV'}) CREATE (ev:PushEvent {time:toInt(1401606330) }) MERGE (u)-[:DO]->(ev)
MERGE (repo:Repository {id:toInt(20051270)})
SET repo.name='Unicode'
MERGE (branch:Branch {ref:'refs/heads/master', repo_id:toInt(20051270)})
MERGE (ev)-[:PUSH_TO]->(branch)
MERGE (branch)-[:BRANCH_OF]->(repo)
MERGE (owner:User {name:'ZhukV'})
MERGE (repo)-[:OWNED_BY]->(owner)
Expl
-> 匹配或创建执行事件的用户 -> 将用户与该事件关联 -> 匹配或创建推送到该用户的仓库 -> 匹配或创建推送到该用户的分支 -> 事件与分支相关联为PUSH_TO -> 分支是仓库的BRANCH_OF -> 匹配或创建仓库的所有者 -> 由某人拥有的仓库
PullRequestEvent
MERGE (u:User {name:'pixelfreak2005'})
CREATE (ev:PullRequestEvent {time:toInt(1401606356) })
MERGE (u)-[:DO]->(ev)
MERGE (pr:PullRequest {html_url:'https://github.com/pixelfreak2005/liqiud_android_packages_apps_Settings/pull/2'})
SET pr += { id:toInt(16573622), number:toInt(2), state:'open'}
MERGE (ev)-[:PR_OPEN]->(pr)
MERGE (ow:User {name:'pixelfreak2005'})
MERGE (or:Repository {id:toInt(20338536), name:'liqiud_android_packages_apps_Settings'})
MERGE (or)-[:OWNED_BY]->(ow)
MERGE (pr)-[:PR_ON_REPO]->(or)
ForkEvent
MERGE (u:User {name:'rudymalhi'})
CREATE (ev:ForkEvent {time:toInt(1401606379) }) MERGE (u)-[:DO]->(ev)
CREATE (fork:Fork:Repository {name:'Full-Stack-JS-Nodember'})
MERGE (ev)-[:FORK]->(fork)-[:OWNED_BY]->(u)
MERGE (bro:User {name:'mgenev'})
MERGE (br:Repository {id:toInt(15503488), name:'Full-Stack-JS-Nodember'})-[:OWNED_BY]->(bro)
MERGE (fork)-[:FORK_OF]->(br)
IssueCommentEvent
MERGE (u:User {name:'johanneswilm'})
CREATE (ev:IssueCommentEvent {time:toInt(1401606384) })
MERGE (u)-[:DO]->(ev)
MERGE (comment:IssueComment {id:toInt(44769338)})
MERGE (ev)-[:ISSUE_COMMENT]->(comment)
MERGE (issue:Issue {id:toInt(34722578)})
MERGE (repo:Repository {id:toInt(14487686)})
MERGE (comment)-[:COMMENT_ON]->(issue)-[:ISSUE_ON]->(repo)
SET repo.name = 'diffDOM'
MERGE (owner:User {name:'fiduswriter'})
MERGE (comment)-[:COMMENT_ON]->(issue)-[:ISSUE_ON]->(repo)-[:OWNED_BY]->(owner)
我倾听所有能提高查询性能的建议:)