深入学习Gremlin(6):循环操作

版权声明:转载请注明出处 https://blog.csdn.net/javeme/article/details/82760106

第6期 Gremlin Steps:
repeat()times()until()emit()loops()

本系列文章的Gremlin示例均在HugeGraph图数据库上执行,环境搭建可参考准备Gremlin执行环境,本文示例均以其中的“TinkerPop关系图”为初始数据,如下图所示:

init-data

上一期:深入学习Gremlin(5):查询路径path

循环操作说明

循环操作是指多次执行某一部分语句,用于语句需要重复运行的场景,比如“查找朋友的朋友的朋友”,可以直接使用循环操作来完成即“查找3层朋友”,下面对具体的循环相关的Step进行说明:

  • repeat(): 指定要重复执行的语句,如repeat(out('friend'))
  • times(): 指定要重复执行的次数,如执行3次repeat(out('friend')).times(3)
  • until(): 指定循环终止的条件,如一直找到某个名字的朋友为止repeat(out('friend')).until(has('name','xiaofang'))
  • emit(): 指定循环语句的执行过程中收集数据的条件,每一步的结果只要符合条件则被收集,不指定条件时收集所有结果
  • loops(): 当前循环的次数,可用于控制最大循环次数等,如最多执行3次repeat(out('friend')).until(loops().is(3))

实例讲解

下面通过实例来深入理解每一个操作。

  1. Step repeat() + times():按照指定的次数重复执行语句

    示例1:

    // 访问某个顶点的OUT邻接点(1次)
    // 注意'okram'是顶点的id
    g.V('okram').repeat(out()).times(1)
    

    g.V(id).repeat(out).times(1)

    示例2:

    // 访问某个顶点的2度双向邻接点
    // 访问第1个顶点的所有邻接点(第1层)
    // 再访问第1层结果顶点的邻接点(第2层)
    g.V('okram').repeat(both()).times(2)
    

    g.V(id).repeat(both).times(2)

    示例3:

    // 访问某个顶点的3度OUT邻接点
    // 访问第1个顶点的所有邻接点(第1层)
    // 再访问第1层结果顶点的邻接点(第2层)
    // 再访问第2层结果顶点的邻接点(第3层)
    g.V('okram').repeat(out()).times(3)
    

    g.V(id).repeat(out).times(3)

    比一比:

    g.V('okram').out().out().out()
    g.V('okram').repeat(out()).times(3)

  2. Step repeat() + until():根据条件来重复执行语句

    示例1:

    // 查询顶点'okram'到顶点'Gremlin'之间的路径
    // 循环的终止条件是遇到名称是'Gremlin'的顶点
    g.V('okram')
     .repeat(out())
     .until(has('name', 'Gremlin'))
     .path()
    

    g.V(id).repeat(out).until(has).path()

    注意1:这里用到了path()来获取经过的路径,path的讲解请参考上一期。

    注意2:until()times()是互斥的,两个语句无法同时存在于同一个循环中。

    注意3:until()放在repeat()之前或之后的顺序是会影响逻辑的,放前面表示先判断再执行,放后面表示先执行后判断。请对比如下两个语句的执行结果:
    g.V('okram').repeat(out()).until(hasLabel('person')).path()
    g.V('okram').until(hasLabel('person')).repeat(out()).path()

  3. Step repeat() + emit():收集执行过程中的数据

    示例1:

    // 查询顶点'okram'的所有OUT可达点的路径
    g.V('okram')
     .repeat(out())
     .emit()
     .path()
    

    g.V(id).repeat(out).emit().path()

    示例2:

    // 查询顶点'okram'的所有OUT可达点的路径
    // 且必须满足是'person'类型的点
    g.V('okram')
     .repeat(out())
     .emit(hasLabel('person'))
     .path()
    

    g.V(id).repeat(out).emit(has).path()

    注意:emit()放在repeat()之前或之后的顺序是会影响结果的,放前面表示先收集再执行,放后面表示先执行后收集。请对比如下两个语句的执行结果:
    g.V('okram').repeat(out()).emit(hasLabel('person')).path()
    g.V('okram').emit(hasLabel('person')).repeat(out()).path()

    示例3:

    // 查询顶点'okram'到顶点'Gremlin'之间的路径
    // 此外还收集过程中的'person'类型的顶点
    g.V('okram')
     .repeat(out())
     .until(has('name', 'Gremlin'))
     .emit(hasLabel('person'))
     .path()
    

    g.V(id).repeat(out).until(has).emit(has).path()

    注意:emit()until()搭配使用时,是“或”的关系而不是“与”的关系,满足两者间任意一个即可。

    示例4:

    // 查询顶点'okram'的2度OUT可达点的路径
    // 此外还收集'person'类型的顶点
    g.V('okram')
     .repeat(out()).times(2)
     .emit(hasLabel('person'))
     .path()
    

    g.V(id).repeat(out).times(2).emit(has).path()

    注意:emit()times()搭配使用时,是“或”的关系而不是“与”的关系,满足两者间任意一个即可。

  4. Step repeat() + loops():根据最大次数限制来重复执行语句

    示例1:

    // 查询顶点'okram'的3度OUT可达点路径
    g.V('okram')
     .repeat(out())
     .until(loops().is(3))
     .path()
    

    g.V(id).repeat(out).until(loops3).path()

    示例2:

    // 查询顶点'okram'到顶点'Gremlin'之间的路径
    // 且之间只相差2跳的距离
    // 其中的and()是指两个条件都满足
    g.V('okram')
     .repeat(out())
     .until(has('name', 'Gremlin')
            .and().loops().is(2))
     .path()
    

    g.V(id).repeat(out).until(has-loops2).path()

综合运用

  1. 查找子树

    // 查找从一个节点出发,到
    // 叶子节点结束的所有路径
    // 这些路径的集合为一颗子树(子图)
    g.V('okram')
     .repeat(out())
     .until(outE().count().is(0))
     .path()
    

    sub-tree

  2. 查找两点之间的最短路径

    // 已知两个顶点'okram'和'javeme',
    // 通过任意关系来找到这两点之间的路径
    // 且限制了最大深度为3
    // 若存在那么第一条结果即是最短路径
    g.V('okram')
     .repeat(bothE().otherV().simplePath())
     .until(hasId('javeme').and().loops().is(lte(3)))
     .hasId('javeme')
     .path()
    

    shortest-path

    注意:bothE().otherV()一般等价于both(),但是在这里有一些差别,后者仅仅返回路径中的顶点信息,前者会把路径中的边信息也返回。

    试一试:将语句中的lte(3)改为lte(4)看看结果有什么变化

猜你喜欢

转载自blog.csdn.net/javeme/article/details/82760106