cayley图数据库

写在前面

  • 态度决定高度!让优秀成为一种习惯!
  • 世界上没有什么事儿是加一次班解决不了的,如果有,就加两次!(- - -茂强)

前瞻

一说到图数据库,大家估计最先想到的是neo4j,不错,neo4j在图数据库中做的是相当成功,但是在你用的时候,你就会考虑其是否开源,是否免费,你要知道,在公司(不是以图数据作为业务主要驱动的公司)对于你的一个小小的项目,公司给你买一个数据库,这是不是很扯淡,所以,你就很想知道,是否有开源的图数据库,当然有。但是今天我是要说一个个人比较喜欢的图数据库,就是cayley,是完全开源的,项目地址是在google旗下
项目地址:https://github.com/cayleygraph/cayley

cayley

一步一步的建立起自己的cayley

我是windows测试的,所以就选了windows包
当然你也可以选择源码,进行自行编译部署
mkdir -p ~/cayley && cd ~/cayley
export GOPATH=pwd
export PATH=$PATH:~/cayley/bin
mkdir -p bin pkg src/github.com/cayleygraph
cd src/github.com/cayleygraph
git clone https://github.com/cayleygraph/cayley
cd cayley
curl https://glide.sh/get | sh
glide install
go build ./cmd/cayley
编译好了就可以测试一下,切换到命令目录
./cayley repl -i data/testdata.nq
当然也可以用http模式
./cayley http -i data/testdata.nq

  • 解压文件夹到指定目录(自己指定)
    找到加压后文件夹中的cayley.exe,这个就是我们需要操作的对象,
    通过官方我们知道cayley需要指定(依赖)三方数据库,如:
    KVs: Bolt, LevelDB
    NoSQL: MongoDB
    SQL: PostgreSQL, CockroachDB, MySQL
    n-memory, ephemeral
    这里我们选择levelDB
  • 把cayley.cfg.example文件重命名为cayley.cfg
    这一步可以不用,因为不影响,我个人比较喜欢标准一点,所以就改了
  • cayley.cfg内容配置
    {
    "database": "leveldb",
    "db_path": "d:/cayley/cayley_db",
    "read_only": false
    }
    这里db_path就是cayley需要创建的levelDB的路径,其他的都是字面意思,如果你想依赖起的数据库,比如 Bolt数据库你可以用一下的配置
    {
    "database": "bolt",
    "db_path": "/tmp/demodb",
    "read_only": false
    }
    更多的配置信息:https://github.com/cayleygraph/cayley/blob/master/docs/Configuration.md
  • 初始化cayley依赖的levelDB
    我们在cmd里边切换到cayley.exe所在的文件夹下
    执行命令:
    cayley.exe init --config=cayley.cfg
    或者用:
    cayley.exe init --db=leveldb --dbpath=d:/cayley/cayley_db
    都可以,这样cayley就会在d:/cayley/cayley_db下初始化一个levelDB数据库了,不信你去文件夹下看看
    当然,你也许会用到其他的数据库,比如 Bolt那你可以用
    cayley.exe init --db=bolt --dbpath=tmp/testdb
    如果是MongoDB那就要用
    cayley.exe init --db=mongo --dbpath=”<HOSTNAME>:<PORT>
    其中,HOSTNAME和PORT指向你的Mongo实例
    依赖的数据库建好了之后,那就给里边添加点数据吧
  • 向cayley里边添加数据
    首先让我们看一下数据的具体格式,在data目录下有个testdata.nq的文本,打开后就是如下的数据
    <alice> <follows> <bob> .
    <bob> <follows> <fred> .
    <bob> <status> "cool_person" .
    <charlie> <follows> <bob> .
    <charlie> <follows> <dani> .
    <dani> <follows> <bob> .
    <dani> <follows> <greg> .
    <dani> <status> "cool_person" .
    <emily> <follows> <fred> .
    <fred> <follows> <greg> .
    <greg> <status> "cool_person" .
    <predicates> <are> <follows> .
    <predicates> <are> <status> .
    <emily> <status> "smart_person" <smart_graph> .
    <greg> <status> "smart_person" <smart_graph> .
    这个就是人的关系数据,第一个是主语subject,第二个是谓语predicate,第三个是宾语object,最后以 . 号结束,其中还有,主题还有一个属性status可以从下图来理解


    关系图(版权归原创)

    图中箭头表示follows的关系,而#括起来的人名表示,这些人有status为cool_person
    下边我们把它加载到我们刚才初始化的levelDB中
    cayley.exe load --config=cayley.cfg --quads=data/testdata.nq
    这样数据就加载到了levelDB中了

  • 启动cayley
    cayley的启动方式有两种,一种是REPL另一种是HTTP
    第一种:REPL
    cayley.exe repl --config=cayley.cfg
    启动后是命令行模式


    cayley的repl启动

    第二种:HTTP
    cayley.exe http --config=cayley.cfg
    启动后控制台


    cayley的http启动

    这样你就可以在浏览器中打开了
http模式的界面

cayley的增删查

cayley只有增、删、查,不同于其他的数据库,cayley少了改的操作,其实大家都知道,所谓的改就是先删在增

  • cayley的增
    比如我要添加一个人叫“leon”,他关注了“alice”,并且他也是一个“cool_person”,那么输入这样的命令即可:
    :a leon follows alice .
    :a leon status cool_person .
  • cayley的删
    比如我刚才添加的“leon”,现在他不想关注“alice”了,那么这样就可以删除刚才建立的关系了:
    :d leon follows alice .
  • cayley的查
    cayley的查提供了两种形式的语言,一种和javascript类似,一种是简化的MQL,这里选择js的查询来阐述一下
    graph对象:graph对象简称g,它是唯一存在的,并由它来说产生query对象,通过query返回各种查询结果,执行方式如下:
    graph.Vertex([nodeId],[nodeId]…) 简写为 g.V
    参数:nodeId(可选):一个字符串,或者字符串列表,代表了查询的起始节点
    返回:query 对象
    从给定的顶点(集)开始一个查询路径,如果没有参数,则认为是图中所有的顶点。
    来看例子:
    g.V().All() //我想看目前图中所有的顶点
    g.V("<alice>").GetLimit(1) //获得alice这个节点
    其中All()方法是query对象的方法,用它可以遍历query对象中,所有的数据。GetLimit(number)也是query对象的方法,它获得迭代集里限定数目的数据。
    getAll

    graph.Morphism() 简写为 g.M()
    无参数
    返回:path对象
    path 对象,它是query对象的父类对象
    path对象由 g.V() 和 g.M() 创建,其中 g.V() 创建了query对象,它是path对象的子类。
    path.Out([predicatePath],[tags])
    参数:predicatePath(可选)下列其中之一
    空或者undifined:所有从这个节点出去的predicate
    一个字符串:从这个节点出去的predicate名字
    字符串列表:从这个节点出去的多个predicate名字
    一个query path 对象: 该对象指向一个predicate集合(跟随者)
    tags(可选参数):下列其中之一
    空或者undifined:没有tags
    一个字符串:向输出集使用的指明predicate的标签
    字符串列表:添加多个tags,这些tags当作keys保存指向输出集的predicate
    例子:
    // 查看charlie follows了谁。结果是 bob and dani
    g.V("<charlie>").Out("<follows>").All()
    // 查看alice follows的人,他们又follows了谁。结果是 fred
    g.V("<alice>").Out("<follows>").Out("<follows>").All()
    // 从dani出去的路径都指向了哪里。 结果是 bob, greg 和 cool_person
    g.V("<dani>").Out().All()
    // 找到所有dani通过follows和status指向的节点。
    // 结果是 bob, greg 和 cool_person
    g.V("<dani>").Out(["<follows>", "<status>"]).All()
    // 找到所有dani通过status指向的节点,并加上tag。
    // 结果是 {"id": cool_person, "pred": "status"}
    g.V("<dani>").Out(g.V("<status>"), "pred").All()
    path.In([predicatePath],[tags])
    与path.Out()用法上相同,只不过是一个是出,一个是入
    // Find the cool people, bob, dani and greg
    g.V("cool_person").In("<status>").All()
    // Find who follows bob, in this case, alice, charlie, and dani
    g.V("<bob>").In("<follows>").All()
    // Find who follows the people emily follows, namely, bob and emily
    g.V("<emily>").Out("<follows>").In("<follows>").All()
    path.InPredicates()
    获得指向一个节点的一个predicates列表
    // bob only has "<follows>" predicates pointing inward
    // returns "<follows>"
    g.V("<bob>").InPredicates().All()
    path.Both([predicatePath],[tags])
    这个就是in和out的合并,出入同查
    g.V("<fred>").Both("<follows>").All()
    path.Count()
    返回结果总数
    path.Except(path)
    与path.Difference(path)是一样的效果,就是一种排除查询
    var cFollows = g.V("<charlie>").Out("<follows>")var dFollows = g.V("<dani>").Out("<follows>")
    // People followed by both charlie (bob and dani) and dani (bob and greg) -- returns bob.
    cFollows.Except(dFollows).All() // The set (dani) -- what charlie follows that dani does not also follow.
    // Equivalently, g.V("<charlie>").Out("<follows>").Except(g.V("<dani>").Out("<follows>")).All()
    path.Filter(args)
    过滤,可以通过传入区间或者匹配字符串来过滤
    path.Intersect(path)
    求交集
    var cFollows = g.V("<charlie>").Out("<follows>")
    var dFollows = g.V("<dani>").Out("<follows>")
    // People followed by both charlie (bob and dani) and dani (bob and greg) -- returns bob.
    cFollows.Intersect(dFollows).All()
    // Equivalently, g.V("<charlie>").Out("<follows>").And(g.V("<dani>").Out("<follows>")).All()
    其他的查询方法就不多说了,如果想了解去这里看看
    https://github.com/cayleygraph/cayley/blob/master/docs/GizmoAPI.md

关系图可视化

这个需要在http模式

  • Query Shape
query shape
query shape
  • Visualize
visualize
visualize

这里要说明一下,0.6.1版本对于可视化页面支持有问题,图形展示不出来,而且query也查不出来数据,不知是否是浏览器问题(我的是chrome),但是0.6.0就可以展示。
下边将用实例介绍如何用cayley做知识图谱,敬请期待!

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 105,085评论 12 126
  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 5,390评论 0 22
  • 我没有勇气提笔写父亲,我的心情万分悲痛,我想在安静的夜晚和您说说话,现在我的泪有一次模糊了双眼,父亲已经成为一个概...
    慧芮阅读 16,172评论 0 2
  • 身边的夫妻是敷欺,不是敷欺的都离婚了。 夫妻关系首先会想到恩爱,恩爱是指心里有对方,看到对方心里有怦然心动的感觉,...
    朵朵颐阅读 42评论 1 4
  • 昨天发了篇和邀请函有关的文章,于是好多小伙伴来私信我 “请问怎么样才可以拿到邀请函啊?” “可以送张票給我吗?” ...
    木易斐然ElvinStarry阅读 2,143评论 0 1