18.模式匹配

18.1、说明

Gremlin中的match()语句为图查询提供了一种基于“模式匹配”的方式,以便用更具描述性的方式进行图查询。match()语句通过多个模式片段traversal fragments来进行模式匹配。这些traversal fragments中会定义一些变量,只有满足所有用变量表示的约束的对象才能够通过,并被放到一个Map<String, Object>中,其中map的key为变量名(label),value为顶点、边、路径或者属性。match()语句的格式为:match(Traversal…)。其中可以有任意多个Traversal,每一个Traversal就是一个“匹配模式”traversal fragment。

match()语句中的“模式”通过MatchAlgorithm来选择匹配顺序,默认的MatchAlgorithm是CountMatchAlgorithm。CountMatchAlgorithm根据过滤强度动态调整“模式匹配”的执行计划(最能够减少规模的“模式”优先匹配),从而优化执行减少资源消耗。因此,当图的规模比较大且用户不知道满足特定模式的数据规模时,使用match()可以自动进行优化,减小操作规模。另外,对于一些图查询场景,相较于单路径遍历,match()语句的“模式匹配”更容易表达需求。

18.2、实例说明

match()语句通过模式匹配生成map

// 对每一个顶点,用以下模式去匹配,满足则生成一个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中选取部分结果

// 对每一个顶点,用以下模式去匹配,满足则生成一个map<String, Object>,不满足则过滤掉
// 模式1:“a”对应当前顶点,且创建了软件“HugeGraph”
// 模式2:“b”对应顶点软件“HugeGraph”
// 模式3:“c”对应创建软件“HugeGraph”的年龄为29的person顶点
// 并选取map中的“a"和”c",对应的对象以”name“属性的值代替
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()语句配合使用,过滤结果

// 对每一个顶点,用以下模式去匹配,满足则生成一个map<String, Object>,不满足则过滤掉
// 模式1:“a”对应当前顶点,且创建了软件“HugeGraph”
// 模式2:“b”对应顶点软件“HugeGraph”
// 模式3:“c”对应创建软件“HugeGraph”的年龄为29的person顶点
// 模式4:”a“和”c“对应的对象不相等
// 并选取map中的“a"和”c",对应的对象以”name“属性的值代替
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

// 对每一个顶点打标签”a“,"a"经过一条OUT方向的”knows“边到达的顶点打标签”b“
// 对”b“中的每一个顶点用以下模式去匹配,满足则生成一个map<String, Object>,不满足则过滤掉
// 模式1:”b“通过一条OUT方向的”created“边到达顶点”c“
// 模式2:”c“不能通过一条IN方向的”created“边到达”a“
// 选取map中的“a",”b“,”c",对应的对象以”name“属性的值代替
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')

注意match(__.as('b').out('created').as('c')中的__.as(b)是读取label标识的对象,as('c')是为新的对象打上label标识