HugeGraph查询语言
一、图基本概念与操作
#查询顶点,一般作为图查询的第1步,后面可以续接的语句种类繁多 g.V() #查询图中所有的边 g.E() g.E().hasLabel('rel_hdfs_path_and_spark_input_processes') g.E().hasLabel('rel_hive_table_and_spark_output_processes') #根据id查询边 g.E('S2:05e980b8-99f8-47b1-9220-b889b88848b8>1>>S1:cc1c92ac-9754-483a-ba62-298cbb39ff8e') #查询所有顶点的id g.V().id() #查询所有边的id g.E().id() #查询所有顶点的label g.V().label() #查询所有边的label g.E().label() #查询所有顶点的属性 g.V().properties() #如果无“price”属性的顶点将跳过 g.V().properties('price') #查询所有边的属性 g.E().properties() #查询所有顶点的属性名称 g.V().properties().key() #查询所有顶点的属性值 g.V().properties().value() #查询所有顶点的属性 g.V().valueMap() #查询所有顶点的属性值 g.V().values()
参考地址:https://blog.csdn.net/javeme/article/details/82501797
二、边的遍历操作
#查询所有顶点 g.V() #查询顶点 g.V().hasLabel('ent_hive_db') g.V().hasLabel('ent_hive_table') g.V().hasLabel('ent_hive_column') #查询边 g.E().hasLabel('rel_hive_db_and_table') g.E().hasLabel('rel_hive_table_and_column') g.E().hasLabel('rel_hive_table_and_storagedesc') g.E().hasLabel('rel_hdfs_path_and_hive_input_processes') #顶点到与其有直接关联的顶点的路径(仅包含顶点)如果想要同时获得经过的边的信息呢?可以用bothE().otherV()替换both() g.V().hasLabel('ent_hive_db').has('db_name','itl').both().path() g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdbfq_moutdrpt_tmp').both().path() #顶点到与其有直接关联的顶点的路径(包含顶点和边) g.V().hasLabel('ent_hive_db').has('db_name','itl').bothE().otherV().path() #先查询图中所有的顶点,然后访问顶点的OUT方向邻接点 g.V().out() g.V().hasLabel('ent_hive_table').out() #访问某个顶点的OUT方向邻接点,注意'5:cc327f17-ec4c-4138-8dba-2ebdfc69340d'是顶点的id,该id是插入顶点时自动生成的 g.V('5:cc327f17-ec4c-4138-8dba-2ebdfc69340d').out() g.V('3:006b8b97-19f5-4127-9d06-63c131fd7eb6').out() #访问某个顶点的OUT方向邻接点且限制仅“rel_hive_table_and_column”类型的边相连的顶点 g.V('3:006b8b97-19f5-4127-9d06-63c131fd7eb6').out('rel_hive_table_and_column') #访问某个顶点的IN方向邻接点 g.V('3:006b8b97-19f5-4127-9d06-63c131fd7eb6').in() g.V('5:cc327f17-ec4c-4138-8dba-2ebdfc69340d').in() #访问某个顶点的IN方向邻接点,且限制了关联边的类型 g.V('1:5b04fe8a-0157-4dcd-ae05-eb191f62871f').in('rel_hive_db_and_table') #访问某个顶点的双向邻接点 g.V('1:5b04fe8a-0157-4dcd-ae05-eb191f62871f').both() g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').both() #访问某个顶点的双向邻接点,且限制了关联边的类型 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').both('rel_hive_db_and_table', 'rel_hive_table_and_column') g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').both('rel_hive_db_and_table') g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').both('rel_hive_table_and_column') #访问某个顶点的OUT方向邻接边 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').outE() #访问某个顶点的OUT方向邻接边,且限制了关联边的类型 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').outE('rel_hive_db_and_table') #访问某个顶点的IN方向邻接边 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').inE() #访问某个顶点的IN方向邻接边,且限制了关联边的类型 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').inE('rel_hive_table_and_column') #访问某个顶点的双向邻接边 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').bothE() #访问某个顶点的双向邻接边,且限制了关联边的类型 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').bothE('rel_hive_table_and_column', 'rel_hive_db_and_table') #访问某个顶点的IN邻接边,然后获取边的出顶点 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').inE().outV() #一般情况下,inE().outV()等价于in() g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').in() #访问某个顶点的OUT邻接边,然后获取边的入顶点 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').outE().inV() #outE().inV()等价于out() g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').out() #访问某个顶点的OUT邻接边,然后获取边的双向顶点 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').outE().bothV() #访问某个顶点的OUT邻接边,然后获取边的伙伴顶点 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').outE().otherV() #访问某个顶点的双向邻接边,然后获取边的伙伴顶点 g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').bothE().otherV() #一般情况下,bothE().otherV()等价于both() g.V('2:05ea2a1c-1f25-4be0-a6fd-f80bdd2fab65').both() #多度查询 g.V('7:06f91c7d-43ba-40ff-8b1a-4dd2b82b504f').out('rel_hdfs_path_and_hive_input_processes').out('rel_hive_table_and_output_processes').out('rel_hive_db_and_table') g.V('7:06f91c7d-43ba-40ff-8b1a-4dd2b82b504f').out('rel_hdfs_path_and_hive_input_processes').out('rel_hive_table_and_output_processes').out('rel_hive_db_and_table').in('rel_hive_db_ddl_and_hive_db')
参考地址:https://blog.csdn.net/javeme/article/details/82627396
三、has条件过滤
#查询label为"ent_spark_process"的顶点 g.V().hasLabel('ent_spark_process') #查询label为"ent_spark_process"或者"ent_hive_process"的顶点 g.V().hasLabel('ent_spark_process', 'ent_hive_process') #查询id为"5:1b2c3756-db70-48b0-9c8d-804407c7363f"的顶点 g.V().hasId('5:1b2c3756-db70-48b0-9c8d-804407c7363f') 查询id为“5:1b2c3756-db70-48b0-9c8d-804407c7363f”或者“7:06f91c7d-43ba-40ff-8b1a-4dd2b82b504f”的顶点 g.V().hasId('5:1b2c3756-db70-48b0-9c8d-804407c7363f','7:06f91c7d-43ba-40ff-8b1a-4dd2b82b504f') #查询“typeName”属性值为“hive_table”的顶点 g.V().has('typeName', 'hive_table') #查询label为“ent_hive_table”且“typeName”属性值为“hive_table”的顶点 g.V().has('ent_hive_table', 'typeName', 'hive_table') #添加其他过滤条件 g.V().has('ent_hive_table', 'typeName', 'hive_table').has('version', gt(-1)) #查询处于激活状态的表 g.V().has('ent_hive_table', 'typeName', 'hive_table').has('status', 'ACTIVE').has('table_name', 'itl_mposdataspare_odsdb_mid_gdbind_h') #查询包含属性“tableType”的顶点 g.V().properties().hasKey('tableType') #查询包含属性值“Beijing”的顶点 g.V().properties().hasValue('itl_mposdataspare_odsdb_mid_gdbind_h') #查询包含属性“lastAccessTime”的顶点 g.V().has('lastAccessTime') #查询没有属性“lastAccessTime”的顶点 g.V().hasNot('lastAccessTime')
参考地址:https://blog.csdn.net/linlin1989117/article/details/82589895
四、图查询返回结果数限制
#查询图中所有顶点的个数 g.V().count() #查询图中类型为“ent_rdbms_table”的顶点数 g.V().hasLabel('ent_rdbms_table').count() #查询图中所有的 “ent_rdbms_table指向ent_hive_table” 的rel_rdbms_table_and_hive_table边数 g.V().hasLabel('ent_rdbms_table').outE('rel_rdbms_table_and_hive_table').count() #查询图中所有顶点的属性数 g.V().properties().count() #不加限制地查询所有类型为“ent_rdbms_column”的顶点 g.V().hasLabel('ent_rdbms_column').range(0, -1) #查询类型为“ent_rdbms_column”的顶点中的第2个到第5个 g.V().hasLabel('ent_rdbms_column').range(2, 5) #查询类型为“ent_rdbms_column”的顶点中的第5个到最后一个 g.V().hasLabel('ent_rdbms_column').range(5, -1) #查询前“n”个元素,相当于range(0, n),查询前两个顶点 g.V().limit(2) #查询前三条边 g.E().limit(3) #tail():与limit()相反,它查询的是后“n”个元素,相当于range(count - n, -1),查询后两个顶点 g.V().tail(2) #查询后三条边 g.E().tail(3) #skip():跳过前“n”个元素,获取剩余的全部元素,跳过前5个,skip(5)等价于range(5, -1) g.V().hasLabel('ent_rdbms_table').skip(5)
参考地址:https://blog.csdn.net/u010260089/article/details/82594300
五、查询路径path
#path(),获取当前遍历过的所有路径,“ent_hive_table”顶点到与其有直接关联的顶点的路径(仅包含顶点) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').both().path() #如果想要同时获得经过的边的信息,可以用bothE().otherV()替换both(),“ent_hive_table”顶点到与其有直接关联的顶点的路径(包含顶点和边) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').bothE().otherV().path() #“HugeGraph”顶点到与其有直接关联的顶点的路径(包含顶点和边),用“name”属性代表person和software顶点,用“weight”属性代表边 g.V().hasLabel('software').has('name','HugeGraph').bothE().otherV().path().by('name').by('weight') #“ent_hive_table”顶点到与其有两层关系的顶点的所有路径(只包含顶点) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').both().both().path() #simplePath(),过滤掉路径中含有环路的对象,只保留路径中不含有环路的对象,“ent_hive_table”顶点到与其有两层关系的顶点的不含环路的路径(只包含顶点) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').both().both().simplePath().path() #cyclicPath(),过滤掉路径中不含有环路的对象,只保留路径中含有环路的对象,“ent_hive_table”顶点到与其有两层关系的顶点的包含环路的路径(只包含顶点) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').both().both().cyclicPath().path() #cyclicPath(),过滤掉路径中不含有环路的对象,只保留路径中含有环路的对象,“ent_hive_table”顶点到与其有三层关系的顶点的包含环路的路径(只包含顶点) g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_indrpt_i').both().both().both().cyclicPath().path()
参考地址:https://blog.csdn.net/linlin1989117/article/details/82625906
六、循环操作
#repeat() + times():按照指定的次数重复执行语句,访问某个顶点的OUT邻接点(1次) g.V('25:1572c928-7117-4851-87d3-29cded7ed7ab').repeat(out()).times(1) #访问某个顶点的2度双向邻接点,访问第1个顶点的所有邻接点(第1层),再访问第1层结果顶点的邻接点(第2层) g.V('25:1572c928-7117-4851-87d3-29cded7ed7ab').repeat(out()).times(2) #repeat() + until():根据条件来重复执行语句,查询顶点'25:1572c928-7117-4851-87d3-29cded7ed7ab'到顶点'ent_rdbms_instance'之间的路径,循环的终止条件是遇到typeName是'rdbms_instance'的顶点 g.V('25:1572c928-7117-4851-87d3-29cded7ed7ab').repeat(out()).until(has('typeName', 'rdbms_instance')).path() g.V().hasLabel('ent_rdbms_column').has('column_name','SSHKTAG').repeat(out()).until(has('typeName', 'hive_db')).path() g.V().hasLabel('ent_rdbms_table').repeat(out()).until(has('typeName', 'hive_db')).path() g.V().hasLabel('ent_rdbms_table').has('table_name','store_sx_yf').repeat(out()).until(has('typeName', 'hive_table')).path() g.V().hasLabel('ent_hive_table').has('table_name','itl_frontdataanalysis_odsdb_basic_store_sx_yf').inE() #repeat() + emit():收集执行过程中的数据,查询顶点'ent_rdbms_column'的所有OUT可达点的路径 g.V().hasLabel('ent_rdbms_column').repeat(out()).emit().path() g.V().hasLabel('ent_rdbms_column').has('column_name','store_xse').repeat(out()).emit().path() g.V().hasLabel('ent_rdbms_column').has('column_id','558cd8f9ae346200ec1e03e51ec576dc').repeat(out()).emit().path() g.V().hasLabel('ent_rdbms_column').has('column_id','f223820cbd3ff1503696bd98c2dee174').repeat(out()).emit().path() g.V().hasLabel('ent_rdbms_column').has('column_id','f223820cbd3ff1503696bd98c2dee174').repeat(both()).emit().path() g.V().hasLabel('ent_rdbms_table').has('db_name','memberfq_result').has('table_name','ds_huiyuan_storefq_xsmx').repeat(out()).emit().path() g.V('2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912').inE() g.V('2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912').inE('rel_hive_table_and_input_processes','rel_hive_table_and_output_processes') #查询顶点'2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912'的所有OUT可达点的路径且必须满足是'ent_hive_db'类型的点 g.V('2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912').repeat(out()).emit(hasLabel('ent_hive_db')).path() #查询顶点'2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912'到顶点'itl'之间的路径,此外还收集过程中的'ent_hive_db'类型的顶点 g.V('2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912').repeat(out()).until(has('db_name', 'itl')).emit(hasLabel('ent_hive_db')).path() #查询顶点'2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912'的2度OUT可达点的路径,此外还收集'ent_hive_db'类型的顶点 g.V('2:a70e2444-6a6b-439b-aa1c-8dfd6bb5c912').repeat(out()).times(2).emit(hasLabel('ent_hive_db')).path() #repeat() + loops():根据最大次数限制来重复执行语句,查询顶点'22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3'的3度OUT可达点路径 g.V('22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3').repeat(out()).until(loops().is(3)).path() #查询顶点'22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3'到顶点'Gremlin'之间的路径且之间只相差2跳的距离,其中的and()是指两个条件都满足 g.V('22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3').repeat(out()).until(has('typeName', 'rdbms_db').and().loops().is(2)).path() #查找子树,查找从一个节点出发,到叶子节点结束的所有路径,这些路径的集合为一颗子树(子图) g.V('22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3').repeat(out()).until(outE().count().is(0)).path() g.V('25:96c41051-ccd1-415f-855d-d988a0840dfc').repeat(out()).until(outE().count().is(0)).path() #查找两点之间的最短路径,已知两个顶点'22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3'和'javeme',通过任意关系来找到这两点之间的路径且限制了最大深度为3,若存在那么第一条结果即是最短路径 g.V('22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3').repeat(bothE().otherV().simplePath()).until(hasId('7388c27f-d0e0-4463-ac43-8902d8f45233').and().loops().is(lte(3))).hasId('7388c27f-d0e0-4463-ac43-8902d8f45233').path() g.V('22:fced3fc3-4bcd-4c9a-bc4e-5b66b72535b3').repeat(bothE().otherV().simplePath()).until(hasId('7388c27f-d0e0-4463-ac43-8902d8f45233').and().loops().is(lte(2))).hasId('7388c27f-d0e0-4463-ac43-8902d8f45233').path()
参考地址:https://blog.csdn.net/javeme/article/details/82760106
七、查询结果排序
#以默认排序输出所有顶点的"typeName"属性值 g.V().values('typeName').order() #以升序输出所有顶点的"name"属性值 g.V().values('typeName').order().by(incr) #以降序输出所有顶点的"typeName"属性值 g.V().values('typeName').order().by(decr) #以随机序输出所有顶点的"typeName"属性值 g.V().values('typeName').order().by(shuffle) #将"ent_rdbms_table"类型的顶点按照"table_update_time"升序(默认)排列输出 g.V().hasLabel('ent_rdbms_table').order().by('table_update_time') #将"ent_rdbms_table"类型的顶点按照"table_update_time"升序(默认)排列,并获取"table_update_time"属性 g.V().hasLabel('ent_rdbms_table').order().by('table_update_time').values('table_update_time') #按照元素属性key的值升序排列 g.V().hasLabel('ent_rdbms_table').order().by('table_update_time',incr).values('table_update_time') #按照元素属性key的值降序排列 g.V().hasLabel('ent_rdbms_table').order().by('table_update_time',decr).values('table_update_time') #按照元素属性key的值随机序排列 g.V().hasLabel('ent_rdbms_table').order().by('table_update_time',shuffle).values('table_update_time')
参考地址:https://blog.csdn.net/u010260089/article/details/82666260?spm=1001.2014.3001.5502
八、数据分组与去重
#不指定任何维度进行分组 g.V().hasLabel('ent_rdbms_table').group() #不指定任何维度进行分组,但数据集中有重复的元素,重复的元素将会被分为一组 g.V().both().hasLabel('ent_rdbms_table').group() #根据table_create_time进行分组 g.V().hasLabel('ent_rdbms_table').group().by('table_create_time') #根据table_create_time进行分组并统计各个table_create_time的数量 g.V().hasLabel('ent_rdbms_table').group().by('table_create_time').by(count()) #根据顶点类别进行分组并统计各个类别的数量 g.V().group().by(label).by(count()) #groupCount():对结果集进行分组计数,不指定任何维度进行分组计数 g.V().hasLabel('ent_rdbms_table').groupCount() #不指定任何维度进行分组计数,但数据集中有重复的元素,重复的元素将会被分为一组 g.V().both().hasLabel('ent_rdbms_table').groupCount #根据table_update_time进行分组计数 g.V().hasLabel('ent_rdbms_table').groupCount().by('table_update_time') #dedup():去除结果集中重复的元素,对一组含有重复顶点的数据进行去重 g.V().both().hasLabel('ent_rdbms_table').dedup() #查看table_update_time当中有哪几种时间table_update_time是可能有重复的,通过dedup去除掉重复的table_update_time g.V().hasLabel('ent_rdbms_table').values('table_update_time').dedup() #从各个table_update_time中选出一个代表 g.V().hasLabel('ent_rdbms_table').dedup().by('table_update_time') #统计顶点的边数量的分布情况,拥有相同数量边的顶点作为一组,并获取每一组的顶点数量,结果相当于:拥有m条边的顶点有n个 g.V().groupCount().by(bothE().count())
参考地址:https://blog.csdn.net/javeme/article/details/82769457
九、条件和过滤
#predicate可以通过test()来获得boolean值,可以用test()测试value是否满足predicate,(3 == 2) eq(2).test(3) #('d' == 'a' || 'd' == 'b' || 'd' == 'c') within('a','b','c').test('d') #(3 > 1 && 3 < 4) inside(1,4).test(3) #not()作用于neq(),等价于eq() not(neq(2)) #and()连接的predicate,是一个新的predicate within(1,2,3).and(not(eq(2))).test(3) #or()连接的predicate,是一个新的predicate inside(1,4).or(eq(5)).test(3) inside(1,4).or(eq(5)).test(5) inside(1,4).or(eq(5)).test(6) #where()有三种使用方式:where(P)、where(String, P)、where(Traversal) #查看“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的合作伙伴 where(P)方式 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a').out('rel_rdbms_table_and_rdbms_db').in('rel_rdbms_table_and_rdbms_db').where(neq('a')) g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a').out('rel_rdbms_table_and_rdbms_db').where(neq('a')) g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a').in('rel_rdbms_table_and_rdbms_db').where(neq('a')) #查看“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的合作伙伴,where(String, P)方式 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a').out('rel_rdbms_table_and_rdbms_db').in('rel_rdbms_table_and_rdbms_db').as('b').where('a',neq('b')) #“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”指向不止一个的顶点,where(Traversal)方式 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out('rel_rdbms_table_and_rdbms_db').in('rel_rdbms_table_and_rdbms_db') .where(out('rel_rdbms_table_and_rdbms_db').count().is(gt(1))) .values('name') #查询”被别人认识“且认识自己的人的年龄大于自己的年龄的人 g.V().as('a') .out('knows').as('b') .where('a', gt('b')).by('age') #where()与match()配合使用,match()可以保证满足某种模式的对象通过 #查看“zhoney”的合作伙伴,并将“zhoney”及其合作伙伴的名字以map输出 #match().where()方式 g.V('zhoney').match(__.as('a').out('created').as('b'), __.as('b').in('created').as('c')). where('a', neq('c')) .select('a','c').by('name') #filter()有三种用法:lambda方式,filter{it.get()…}、Traversal方式,filter(Traversal)、特定filter step方式 #查找图中的“ent_rdbms_table”顶点 #lambda方式 g.V().filter {it.get().label() == 'ent_rdbms_table'} #查找图中的“ent_rdbms_table”顶点,Traversal方式 g.V().filter(label().is('ent_rdbms_table')) #查找图中的“ent_rdbms_table”顶点 #特定filter step方式 g.V().hasLabel('ent_rdbms_table')
参考地址:https://blog.csdn.net/linlin1989117/article/details/82692587?spm=1001.2014.3001.5502
十、逻辑运算
#is(),筛选出顶点属性“table_name”等于diralcdtl的属性值,与`is(P.eq(diralcdtl))`等效 g.V().values('table_name').is('diralcdtl') #筛选出顶点属性“age”大于等于28的属性值 g.V().values('age').is(gte(28)) #筛选出顶点属性“age”属于区间(27,35)的属性值 g.V().values('age').is(inside(27, 35)) #筛选出由两个或两个以上的人参与创建(“created”)的顶点,注意:这里筛选的是顶点 g.V().where(__.in('created').count().is(gt(2))).values('name') #筛选出有创建者(“created”)的年龄(“age”)在20~29之间的顶点 g.V().where(__.in('created').values('age').is(between(20, 29))).values('name') #所有包含出边“rel_hive_table_and_output_processes”的顶点的名字“typeName” g.V().and(outE('rel_hive_table_and_output_processes')).values('typeName') #所有包含出边“rel_hive_table_and_output_processes”和“rel_rdbms_table_and_hive_table”的顶点的名字“typeName” g.V().and(outE('rel_hive_table_and_output_processes'), outE('rel_rdbms_table_and_hive_table')).values('typeName') #包含边“created”并且属性“age”为28的顶点的名字“name” g.V().and(outE('created'), values('age').is(28)).values('name') #所有包含出边“rel_hive_table_and_output_processes”的顶点的名字“typeName”,只有一个条件时,and()与or()的效果一样的。 g.V().or(outE('rel_hive_table_and_output_processes')).values('typeName') #所有包含出边“rel_hive_table_and_output_processes”或“rel_rdbms_table_and_hive_table”的顶点的名字“typeName” g.V().or(outE('rel_hive_table_and_output_processes'), outE('rel_rdbms_table_and_hive_table')).values('typeName') #包含边“created”或属性“age”为28的顶点的名字“name” g.V().or(outE('created'), values('age').is(28)).values('name') #筛选出所有不是“person”的顶点的“label” g.V().not(hasLabel('person')).label() #筛选出所有包含不少于两条(大于等于两条)“created”边的“person”的名字“name” g.V().hasLabel('person').not(out('created').count().is(lt(2))).values('name') #与(含有小于等于一条“created”边,年龄不等于28) g.V().hasLabel('person') .and(outE('created').count().is(lte(1)), values("age").is(P.not(P.eq(28)))) .values('name') #非(或(含有多于一条“created”边,年龄等于28)) g.V().hasLabel('person') .not(or(out('created').count().is(gt(1)), values('age').is(28))) .values('name')
参考地址:https://blog.csdn.net/u010260089/article/details/82769959
十一、统计运算
#计算所有“person”的“age”的总和 g.V().hasLabel('person').values('age').sum() #计算所有“person”的“created”出边数的总和 g.V().hasLabel('person').map(outE('created').count()).sum() #计算所有“person”的“age”中的最大值 g.V().hasLabel('person').values('age').max() #计算所有“person”的“created”出边数的最大值 g.V().hasLabel('person').map(outE('created').count()).max() #计算所有“person”的“age”中的最小值 g.V().hasLabel('person').values('age').min() #计算所有“person”的“created”出边数的最小值 g.V().hasLabel('person').map(outE('created').count()).min() #计算所有“person”的“age”的均值 g.V().hasLabel('person').values('age').mean() #计算所有“person”的“created”出边数的均值 g.V().hasLabel('person').map(outE('created').count()).mean()
参考地址:https://blog.csdn.net/u010260089/article/details/82787808
十二、数学运算
比如按照年龄段进行统计 g.V().hasLabel('person') .groupCount().by(values('age').math('floor(_/10)*10')) .order(local).by(values,desc)
参考地址:https://blog.csdn.net/linlin1989117/article/details/82849477
十三、路径选取与过滤
#as()...select():对路径中结果进行选取,从路径中选取第1步和第3步的结果作为最终结果 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a') .out().as('b') .out().as('c') .select('a', 'c') #从集合中选择最后一个元素 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as("a") .repeat(out().as("a")).times(2) .select(last, "a") g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as("a") .repeat(out().as("a")).times(2) .select(all, "a") g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as("a") .repeat(out().as("a")).times(2) .select(first, "a") #通过by()来指定选取的维度 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a') .out().as('b') .out().as('c') .select('a', 'c') .by('typeName').by('typeName') #从map中选择指定key的值 g.V().valueMap().select('typeName').dedup() #as()...where():以条件匹配的方式进行路径结果选取,选取满足第1步和第3步“version”属性相等的路径 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a') .out().as('b').out().as('c') .where('a', eq('c')).by('version') .select('a', 'b', 'c').by('typeName') #as()+match():以模式匹配的方式进行路径结果选取,选取满足两个模式的路径: #1.第3步有OUT节点 #2.第3步的OUT节点的指定路径不允许回到第二步的节点 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a').out().as('b') .match(__.as('b').out().as('c'), __.not(__.as('c').out().in('define').as('b'))) .select('a','b','c').by('typeName') #as()+debup():路径去重,以路径中的前3步作为去重依据,对路径进行去重 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').as('a') .out().as('b').out().as('c').in() .dedup('a', 'b', 'c').path() #查询支持Gremlin语言的软件,至少由2个相互认识的且在北京的作者完成,获取支持Gremlin语言的软件,并且作者是至少为2个相互认识的人,且这两个作者都在北京 g.V('3:Gremlin').in('supports').as('software') .match( __.as('software').in('created').as('person1'), __.as('person1').both('knows').as('person2'), __.as('person2').out('created').as('software'), __.as('person1').has('addr', 'Beijing'), __.as('person2').has('addr', 'Beijing') ) .select('software').dedup() #查询支持Gremlin语言的软件的作者,并按边权重排序,获取支持Gremlin语言的软件,并查找其作者,并对中间经过的边打标签,按照边的权重进行排序,选取软件、权重、作者作为结果 g.V('3:Gremlin').in('supports').as('s') .inE('created').as('e').outV().as('t') .order().by(select('e').by('weight'), decr) .select('s', 'e', 't').by('name').by('weight')
参考地址:https://blog.csdn.net/javeme/article/details/88417208
十四、分支
#if-then-else型choose()语句,查找所有的“person”类型的顶点,如果“age”属性小于等于20,输出他的朋友的名字,如果“age”属性大于20,输出他开发的软件的名字 #choose(condition, true-action, false-action) g.V().hasLabel('person') .choose(values('age').is(lte(20)), __.in('knows'), __.out('created')).values('name') #option()型choose()语句,查找所有的“person”类型的顶点,如果“age”属性等于0,输出名字,如果“age”属性等于28,输出年龄,如果“age”属性等于29,输出他开发的软件的名字 #choose(predicate).option().option()... g.V().hasLabel('person') .choose(values('age')) .option(0, values('name')) .option(28, values('age')) .option(29, __.out('created').values('name')) #查找所有顶点,类型为“person”的顶点输出其创建的软件的“name”属性,否则输出顶点自身的“name”属性 g.V().choose(hasLabel('person'), out('created')) .values('name') #查找所有顶点,类型为“person”的顶点输出其创建的软件的“name”属性,否则输出顶点自身的“name”属性 g.V().choose(hasLabel('person'), out('created'), identity()) .values('name') #choose()和option()配合使用时,还提供了一个none,不满足其他选项的对象,执行none选项的traversal #查找所有类型为“person”的顶点,“name”属性为“Zhoney Zhang”的输出其“age”属性,否则输出顶点的“name”属性 g.V().hasLabel('person') .choose(values('name')) .option('Zhoney Zhang', values('age')) .option(none, values('name')) #branch()有三种用法:lambda方式,filter{it.get()…}、Traversal方式,filter(Traversal)、特定branch step方式 #查询所有顶点,“name”属性值为“HugeGraph”的顶点输出其“lang”属性,“name”属性值不为“HugeGraph”的顶点输出其“name”属性 #lambda方式 g.V().branch {it.get().value('name')} .option('HugeGraph', values('lang')) .option(none, values('name')) #traversal方式 g.V().branch(values('name')) .option('HugeGraph', values('lang')) .option(none, values('name')) #特定branch step方式 g.V().choose(has('name','HugeGraph'), values('lang'), values('name'))
参考地址:https://blog.csdn.net/linlin1989117/article/details/82703743
十五、合并
#coalesce(),按优先级寻找到顶点“HugeGraph”的以下边和邻接点,找到一个就停止 #1、“implements”出边和邻接点 #2、“supports”出边和邻接点 #3、“created”入边和邻接点 g.V('3:HugeGraph').coalesce(outE('implements'), outE('supports'), inE('created')).inV().path().by('name').by(label) #按优先级寻找到顶点“HugeGraph”的以下边和邻接点,找到一个就停止(调换了示例1中的1和2的顺序) #1、“supports”出边和邻接点 #2、“implements”出边和邻接点 #3、“created”入边和邻接点 g.V('3:HugeGraph').coalesce(outE('supports'), outE('implements'), inE('created')).inV().path().by('name').by(label) #optional()查找顶点"linary"的“created”出顶点,如果没有就返回"linary"自己 g.V('linary').optional(out('created')) #查找每个“person”顶点的出“knows”顶点,如果存在,然后以出“knows”顶点为起点,继续寻找其出“created”顶点,最后打印路径 g.V().hasLabel('person').optional(out('knows').optional(out('created'))).path() #union()寻找顶点“linary”的出“created”顶点,邻接“knows”顶点,并将结果合并 g.V('linary').union(out('created'), both('knows')).path() g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').union(out('rel_rdbms_table_and_rdbms_db')).path() #寻找顶点“HugeGraph”的入“created”顶点(创作者),出“implements”和出“supports”顶点,并将结果合并 g.V('3:HugeGraph').union(__.in('created'), out('implements'), out('supports'), out('contains')).path()
参考地址:https://blog.csdn.net/u010260089/article/details/82837664
十六、结果聚集与展开
#aggregate():聚集路径中的结果,收集第1步的结果到集合'x'中 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out().aggregate('x') #收集第1步的结果到集合'x'中,并通过cap取出结果,与示例1比较,结果的层次更深了 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out().aggregate('x').cap('x') g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out().aggregate('x').select('x') #store():以Lazy的方式来收集结果,以Lazy方式收集,后续步骤使用limit限制时,路径中取到第2个结果时将会停止,因此集合中有2个元素。 g.V().store('x').by('typeName').limit(1).cap('x') #unfold():以把集合展开、平铺,将集合‘x’展开(层级变少了) g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out() .aggregate('x').by('typeName') .cap('x').unfold() #fold():将元素折叠为集合,将属性折叠起来(层级变深) g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out() .values('typeName').fold() #统计所有'name'属性的长度,其中通过lambuda表达式累加字符串长度 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out().values('typeName') .fold(0) {a,b -> a + b.length()}
参考地址:https://blog.csdn.net/javeme/article/details/88576363
十七、模式匹配
#对每一个顶点,用以下模式去匹配,满足则生成一个map<String, Object>,不满足则过滤掉 #模式1:“a”对应当前顶点,且创建了软件“HugeGraph” #模式2:“b”对应顶点软件“HugeGraph” #模式3:“c”对应创建软件“HugeGraph”的年龄为29的person顶点 g.V().match(__.as('a').out('created').has('name', 'HugeGraph').as('b'), __.as('b').in('created').has('age', 29).as('c')) #match()语句可以与select()语句配合使用,从Map<String, Object>中选取部分结果 g.V().match(__.as('a').out('created').has('name', 'HugeGraph').as('b'), __.as('b').in('created').has('age', 29).as('c')) .select('a', 'c').by('name') #match()语句可以与where()语句配合使用,过滤结果 g.V().match(__.as('a').out('created').has('name', 'HugeGraph').as('b'), __.as('b').in('created').has('age', 29).as('c')) .where('a', neq('c')) .select('a', 'c').by('name') #match()语句中可以使用外部的label g.V().as('a').out('knows').as('b') .match(__.as('b').out('created').as('c'), __.not(__.as('c').in('created').as('a'))) .select('a','b','c').by('name')
参考地址:https://blog.csdn.net/linlin1989117/article/details/82855931
十八、随机过滤与注入
#sample()从所有顶点的出边中随机选择2条 g.V().outE().sample(2) #从所以顶点的“typeName”属性中随机选取3个 g.V().values('typeName').sample(3) #从所有的“ent_rdbms_column”中根据“sort_no”随机选择3个 g.V().hasLabel('ent_rdbms_column').sample(3).by('sort_no') #与local联合使用做随机漫游(从某个顶点出发,随机选一条边,走到边上的邻接点;再以该点为起点,继续随机选择边,走到邻接点…) #从顶点“HugeGraph”出发做3次随机漫游 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e') .repeat(local(bothE().sample(1).otherV())) .times(3) .path() #coin()每个顶点按0.5的概率过滤 g.V().coin(0.5) #每个顶点按0.0的概率过滤 g.V().coin(0.0) #每个顶点按1.0的概率过滤 g.V().coin(1.0).count() #constant()输出所有“person”类顶点的“name”属性,否则输出“inhuman”(非人类) g.V().choose(hasLabel('person'), values('name'), constant('inhuman')) #与示例1功能相同,使用“coalesce”Step 实现 g.V().coalesce(hasLabel('person').values('name'), constant('inhuman')) #inject(),给顶点“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的添加一个“DELETE” g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e') g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in() g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in('rel_rdbms_column_and_rdbms_table') g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in('rel_rdbms_column_and_rdbms_table').values('status') g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in('rel_rdbms_column_and_rdbms_table').values('status').inject('DELETE') #在示例1的基础上计算每个元素的长度(“status”属性值的长度),可以看到,注入的元素“DELETE”与原生的元素一样参与了计算 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in('rel_rdbms_column_and_rdbms_table').values('status').inject('DELETE') .map {it.get().length()} #在示例2的基础上计算走过的路径 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').in('rel_rdbms_column_and_rdbms_table').values('status').inject('DELETE') .map {it.get().length()}.path() #使用inject创建出两个元素(顶点的id),并使用该元素作为id获取顶点及其属性“name” inject('javeme', 'linary', 'zhoney').map {g.V(it.get()).next()}.values('name') #使用inject创建出一个“person”(顶点label),并使用该元素作为label获取顶点及其属性“name” inject('person').flatMap {g.V().hasLabel(it.get())}.values('name')
参考地址:https://blog.csdn.net/u010260089/article/details/82900950
十九、结果存取口袋sack
#withSack()…sack(): 利用口袋来存取结果,创建一个包含常数1的口袋,并且在最终取出口袋中的值 g.withSack(1).V().sack() #创建一个包含一个float数值的口袋,并且在最终取出口袋中的值 g.withSack{new Random().nextFloat()}.V().sack() g.withSack(new Random().nextFloat()).V().sack() #通过sum求和的方式把数据放入口袋 g.withSack(0).V() .repeat(outE().sack(sum).by('weight').inV()) .times(3).sack() #通过lambda函数来指定放入口袋的行为,注意:提供的初始值为Map类型,而且当traverser分裂时会拷贝Map g.withSack{[:]}{it.clone()} .V().out().out().dedup() .sack{m,v -> m[v.value('name')] = v.value('lang'); m} .sack() #去掉分裂函数后看看效果: g.withSack{[:]} .V().out().out().dedup() .sack{m,v -> m[v.value('name')] = v.value('lang'); m} .sack() #平均获取口袋中的值 g.withSack(1.0).V('javeme') .out('knows').out('created') .barrier(normSack).sack()
参考地址:https://blog.csdn.net/javeme/article/details/89038027
二十、遍历栅栏barrier
#barrier(): 遍历时设置栅栏,将所有顶点打印出来,打印完一轮之后再打印一轮 def list=[] g.V().sideEffect{list.add("first: "+it)} .barrier() .sideEffect{list.add("second: "+it)} .iterate() list #打印first后打印second,直到一轮所有的顶点都完成 def list=[] g.V().sideEffect{list.add("first: "+it)} .sideEffect{list.add("second: "+it)} .iterate() list #禁用自动barrier策略 g = g.withoutStrategies(LazyBarrierStrategy) g.V() .both().barrier() .both().barrier() .both().barrier() .both().barrier() .both().barrier() .groupCount() .order(local).by(values, decr) #通过lambda函数来指定放入口袋的行为,注意:提供的初始值为Map类型,而且当traverser分裂时会拷贝Map g = g.withoutStrategies(LazyBarrierStrategy) g.V() .both() .both() .both() .both() .both() .groupCount() .order(local).by(values, decr)
参考地址:https://blog.csdn.net/javeme/article/details/89182912
二十一、局部操作local
#不使用local() g.V().hasLabel('ent_rdbms_column').as('aa') .properties('sort_no').order().by(value).limit(2) .value().as('sort_no') .select('aa','sort_no').by('typeName').by() #使用local() g.V().hasLabel('ent_rdbms_column').as('aa') .local(properties('sort_no').order().by(value).limit(2)) .value().as('sort_no') .select('aa','sort_no').by('typeName').by() #查询ent_rdbms_column的属性Map g.V().hasLabel('ent_rdbms_column').has('sort_no',16) .propertyMap() #查询ent_rdbms_column的属性个数 g.V().hasLabel('ent_rdbms_column').has('sort_no',16) .propertyMap().count() g.V().hasLabel('ent_rdbms_column').has('sort_no',16) .propertyMap().count(local) #数目最多的顶点类型的顶点数目 g.V().groupCount().by(label).select(values).max(local) #所有顶点的属性列表中的第一个属性 g.V().valueMap().limit(10) g.V().valueMap().limit(local, 10) #dedup():所有顶点一步邻居中所有的software g.V().both().group().by(label).select('ent_rdbms_column').dedup(local) #order():所有顶点按类型计数并按数目由多到少排序 g.V().groupCount().by(label).order().by(values, decr) g.V().groupCount().by(label).order(local).by(values, decr) #sample():所有顶点作为一个集合,从中采样2个 g.V().fold().sample(local,2)
参考地址:https://blog.csdn.net/linlin1989117/article/details/82859866
二十二、遍历终止terminal
#hasNext(),判断顶点“linary”是否包含“created”出顶点 g.V('linary').out('created').hasNext() #判断顶点“linary”是否包含“knows”出顶点 g.V('linary').out('knows').hasNext() #next(),获取顶点“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的“rel_rdbms_table_and_rdbms_db”出顶点集合的下一个(第1个), g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out('rel_rdbms_table_and_rdbms_db').next() g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').next() #g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out('rel_rdbms_table_and_rdbms_db')返回的是一个遍历器(迭代器), #每次执行这句话实际上都是获取的迭代器的第一个元素,那如果想获取第二个元素该怎么写呢? #很简单,执行两次next()即可,但是这里的前提条件是遍历器中确实存在多个元素。 #获取顶点“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的“rel_rdbms_table_and_rdbms_db”入顶点集合的下一个(第2个) it = g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db') it.next() it.next() #获取顶点“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的“rel_rdbms_table_and_rdbms_db”入顶点集合的前两个 g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').next(2) #试图获取顶点“25:5f16a7ef-71b1-43be-bde1-5ab83640f76e”的“rel_rdbms_table_and_rdbms_db”出顶点集合中的下一个 g.V('25:5f16a7ef-71b1-43be-bde1-5ab83640f76e').out('rel_rdbms_table_and_rdbms_db').tryNext() #获取23:a3782e84-2bd6-4e52-8989-035740da0f68顶点的“rel_rdbms_table_and_rdbms_db”入集合,放入List中,允许包含重复结果 g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').toList() #toSet(),获取23:a3782e84-2bd6-4e52-8989-035740da0f68顶点的“rel_rdbms_table_and_rdbms_db”入集合,放入Set中,不允许包含重复结果 g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').toSet() #toBulkSet(),获取23:a3782e84-2bd6-4e52-8989-035740da0f68顶点的“rel_rdbms_table_and_rdbms_db”入集合,放入BulkSet中,允许包含重复结果,排序 g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').toBulkSet() #fill(),创建一个List,获取23:a3782e84-2bd6-4e52-8989-035740da0f68顶点的“rel_rdbms_table_and_rdbms_db”入集合,并放入该List中 results = [] g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').fill(results) results #iterate(),迭代所有“ent_hive_db”顶点 it = g.V().hasLabel('ent_hive_db').iterate() it.hasNext()
参考地址:https://blog.csdn.net/u010260089/article/details/82969173
二十三、转换操作map/flatMap
#map(),获取顶点“3:HugeGraph”的入“rel_rdbms_table_and_rdbms_db”顶点的“typeName”属性,其实可以理解为顶点对象转化成了属性值对象 g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').map(values('typeName')) g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').map {it.get().value('typeName')} #先获取顶点“23:a3782e84-2bd6-4e52-8989-035740da0f68”的入“rel_rdbms_table_and_rdbms_db”顶点,再将每个顶点转化为出边(一条) g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').map(outE()) #flatMap(),先获取顶点“23:a3782e84-2bd6-4e52-8989-035740da0f68”的入“rel_rdbms_table_and_rdbms_db”顶点,再将每个顶点转化为出边(多条) g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in('rel_rdbms_table_and_rdbms_db').flatMap(outE()) g.V('23:a3782e84-2bd6-4e52-8989-035740da0f68').in().flatMap(outE())
参考地址:https://blog.csdn.net/u010260089/article/details/82970917
二十四、附加操作sideEffect
参考地址:https://blog.csdn.net/javeme/article/details/89184241
二十五、执行统计和分析
参考地址:https://blog.csdn.net/linlin1989117/article/details/82859884