知识图谱、图数据库神器——Grakn

知识图谱、图数据库神器——Grakn

  1. 介绍什么是grakn

    可用于创建知识图谱或图数据库。里边会存节点数据 和 节点之间的关系。并且是支持分布式的。官方提供了java、node、python的三种语言的封装包。是基于gRPC 的方式调用

  2. 安装grakn

    • 支持linux、mac os x、windows平台、docker安装

    • 由于这个数据库数据存储用的是cassandra数据库,所以需要先安装Apache Cassandra 3.11.x and untar it

      我个人用的是docker部署

      docker pull graknlabs/grakn:latest
      
      docker run \
      --name grakn \
      -d \
      --restart=always \
      -v /opt/grakn/db/:/grakn-core-all-linux/server/db/ \
      -p 48555:48555 \
      graknlabs
      
      做了数据库文件的映射 ,其实是映射的cassandra的db位置。docker里自带cassandra服务
      
      docker exec -ti grakn bash -c '/grakn-core-all-linux/grakn console' 
      或者
      docker exec -it grakn bash
      cd grakn-core-all-linux
      ./grakn console -k xxx
      
  3. 创建表结构。数据库肯定要先定义表结构。当然官方支持的java等语言都有创建的步骤。但是感觉很繁琐而且不实用。没想到谁会频繁的去修改表结构。所以这里介绍的graql的写法。就是相当于sql的写法

    • 创建表结构第一步 了解表结构

      实体名 就是表名 entity
      属性   就是字段  attribute 
      主键   就是把属性设置成唯一键 key name
      实体有一个角色的概念  这个主要是为了统一设置关系的 例如一部分实体有个角色是消费者  一部分实体的角色是生产者 那可能定义一种关系由生产者指向消费者
      这就是role
      
      还有实体之间的关系 relation  连线就是根据这个关系链接的
      
    • 了解实体

      比较牛的是他们的实体是可以继承的  跟java里的继承理解一样
      post sub entity, ## entity这是个基类 实体都继承在这
        plays replied-to,
        plays tagged-in,
        plays reacted-to;
      
      comment sub post,
        has content,
        plays attached-to;
      
      media sub post,
        has caption,
        has file,
        plays attached;
      video sub media;
      photo sub media;
      
      更牛是的还有抽象类
      post sub entity, abstract; 
      
  • 了解关系relation

    可以有多个关系 就是会有多个连线 
    
    define
    
    friendship sub relation,
      relates friend,
      plays requested-friendship;
    
    friend-request sub relation,
      relates requested-friendship,
      relates friendship-requester,
      relates friendship-respondent;
    
    person sub entity,
      plays friend,
      plays friendship-requester,
      plays friendship-respondent;
      
      relation也是有属性的
      friend-request sub relation,
      has approved-date,
    
  • 了解语法.直接上例子

    依次定义 属性 实体 关系即可

    efine
    
    ## 先定义属性
    identifier sub attribute,
       value string;
    naptan-id sub attribute,
       value string;
    name sub attribute,
       value string;
    lat sub attribute,
       value double;
    lon sub attribute,
       value double;
    duration sub attribute,
       value double;
    distance sub attribute,
       value double;
    
    ## 在定义实体 因为实体会用到上边定义的属性
    station sub entity,
       has naptan-id,
       has name,
       has lat,
       has lon,
       plays stop,
       plays beginning,
       plays end,
       plays origin,
       plays destination,
       plays contained-station;
    
    tube-line sub entity,
       has name,
       plays route-operator;
    
    route-section sub entity,
       has identifier,
       has duration,
       plays section,
       plays service;
    
    ## 定义关系 关系里包括了属性 和 角色之间的联系,这个角色是在定时实体时候定义的
    route sub relation,
       has identifier,
       relates section,
       relates stop,
       relates origin as stop,
       relates destination as stop,
       relates route-operator;
    
    tunnel sub relation,
       has identifier,
       has distance,
       relates beginning,
       relates end,
       relates service;
    
    zone sub relation,
       has name,
       relates contained-station;
    
  1. 上边把表结构写好之后就要导入到数据库中了

    导入的语句是:
    test是表名 后边是你写的数据表结构的文件
    当然如果是在docker里要做个映射进来 或者通过docker cp拷贝进来
    ./grakn console --keyspace test --file path/to/the/schema.gql
    
  2. 表结构创建完了,接下来就是给表里写输入了 增、删、改、查

    增加

    isa 是实体的时候写 $p

    insert $p isa person,   $p就是自己的定义的变量可以随便起名字$aaa isa表明是实体 必须用isa
    has full-name "John Parkson", has 属性名 具体的值
    has gender "male", 
    has email "john.parkson@gmail.com", 
    has phone-number "+44-1234=567890";
    
    插入就这样写
    

    删除

    match $p isa person, has email "raphael.santos@gmail.com"; 
    match是查找的意思 意识是删除先查找出一个实体的变量$p,根据条件 email=“raphael.santos@gmail.com”  
    delete $p isa person; 然后再删掉
    

    修改 其实是先删除再添加

    ## 先根据条件查找
    match $org isa organisation, has name "Medicely", has registration-number $rn; 
    ## 根据查找到的那条数据删掉属性的值
    delete $org has registration-number $rn;
    ##再找到那条数据 
    match $org isa organisation, has name "Medicely"; 
    ## 给那个属性插入新的值
    insert $org has registration-number "81726354";
    

    查找

    match $p isa person; get; limit 1; 查找person表的所有数据,但是返回的内容里只有id,如果要先都返回需要加上返回的属性
    这一点比较麻烦,但是估计考虑的是性能
    

三、客户端java的封装

  1. maven引入依赖

     <!-- 他们自己管理的没有放到maven库 所以需要指定一下-->
     <repositories>
            <repository>
                <id>repo.grakn.ai</id>
                <url>https://repo.grakn.ai/repository/maven/</url>
            </repository>
        </repositories>
        <!--以下这两个可以访问上边的地址找最新的版本配置以下,我目前用的都是最新的-->
        <!-- 操作gql的依赖-->
         <dependency>
                <groupId>io.graql</groupId>
                <artifactId>graql-lang</artifactId>
                <version>1.0.7</version>
            </dependency>
        <!--grpc连接和执行的封装-->    
            <dependency>
                <groupId>io.grakn.client</groupId>
                <artifactId>grakn-client</artifactId>
                <version>1.8.1</version>
            </dependency>
    
  1. 加载schema,当然通过上边gql导入也是可以的,这里主要介绍java的导入方式

    
            GraknClient client = new GraknClient("http://192.168.1.111:48555");
    
            GraknClient.Session session = client.session("test");
            GraknClient.Transaction transaction = session.transaction().write();
    
            try {
                byte[] encoded = Files.readAllBytes(Paths.get("schemas/test.gql"));
                String query = new String(encoded, StandardCharsets.UTF_8);
                transaction.execute((GraqlDefine) Graql.parse(query));
                transaction.commit();
                System.out.println("Loaded the " + graknClientServer.getKeyspaceName() + " schema");
            } catch (IOException e) {
                transaction.close();
                session.close();
                client.close();;
                e.printStackTrace();
            }
         //注意关闭连接 否则会造成连接数过多,并且jvm里的资源也无法释放 肯定会崩
            transaction.close();
            session.close();
            client.close();;
    
  1. 然后也是增删改查

    增加

           //entity 这个参数是定义的实体 map参数是实体里的属性和要添加的值
           StatementInstance hasSql = var("p").isa(entity);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                hasSql = hasSql.has(entry.getKey(), entry.getValue());
            }
            GraqlInsert query = Graql.insert(hasSql);
            
            GraknClient.Transaction.QueryFuture<List<ConceptMap>> execute = transaction.execute(query);
            List<ConceptMap> conceptMaps = execute.get();
            insertId = conceptMaps.get(0).get("p").id().toString();
            transaction.commit();
            
    

    删除

    //参数为id  id即数据库的自己的 ‘VXXXX’
    GraqlDelete query = Graql.match(
                    var("p").id(id)
            ).delete(var("p"));
    transaction.execute(query);
    transaction.commit();
    

    修改

    //参数id 是要修改的那条数据的id 是“VXXX”。 参数map是要修改的字段和字段的值
    
    //1。 删除属性的值
    for (Map.Entry<String, String> entry : map.entrySet()) {
     GraqlDelete delete_query = Graql.match(
         var("m").id(id).has(entry.getKey(), var("rn"))
     ).delete(var("rn"));
     transaction.execute(delete_query);
    }
    
    //2. 添加属性
    StatementInstance has = null;
     for (Map.Entry<String, String> entry : map.entrySet()) {
         if (null == has) {
             has = var("m").has(entry.getKey(), entry.getValue());
     } else {
         has = has.has(entry.getKey(), entry.getValue());
     }
    }
    
    GraqlInsert insert_query = Graql.match(
     var("m").id(id)
    ).insert(
     has
    );
    transaction.execute(insert_query);
    transaction.commit();
    

           //参数为entity 实体名 参数params为hashmap "name"=>["like","测试"]  参数order为排序方式
           
           String queryEntity = " $" + entity + " isa " + entity;
            //显示的值
            for(Map.Entry<String, List<String>> entry: params.entrySet()) {
                queryEntity = queryEntity + ", has " + entry.getKey()+ " $" + entry.getKey();
            }
            queryEntity += ";";
            
            for(Map.Entry<String, List<String>> entry: params.entrySet()) {
                if(entry.getValue().size() > 0) {
                    queryEntity = queryEntity + " $" + entry.getKey() + " " + queryMap.get(entry.getValue().get(0)) + " '" + entry.getValue().get(1) + "';";
                }
            }
    
            List<String> queryAsList = Arrays.asList(
                    "match ",
                    queryEntity,
                    "get;sort $"+order+" asc;"
            );
            System.out.println("\nQuery:\n" + String.join("\n", queryAsList));
            String query = String.join("", queryAsList);
    
            List<Map<String, String>> result = new ArrayList<>();
    
            GraknClient.Transaction.QueryFuture<List<ConceptMap>> execute = transaction.execute((GraqlGet) parse(query));
            List<ConceptMap> answers = execute.get();
    

    当然最基本的节点操作就是以上的这些方法。基本的入门应该没问题了

    后续如果有需要大的话

    会将优化好的代码和关系的操作开源到github上

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343