gremlin语法详解


初步认识

点:蓝色的圈代表顶点(查询语句中的V()),圈中的person代表顶点的名称,name和age为顶点的属性。

边:黑色的线代表边(查询语句中的E()),线上的knows代表边的名称,weight为边的属性。

 

一、Lambda Step

四个基础的步骤:map ,flatMap ,filter,sideEffect,branch

1. 查找节点属性

(1). V(1)=查询图中第一个顶点  .out() = 输出的顶点  .values("name") = 属性为name的值 

(查询第一个顶点所有边中向外指的顶点,返回这些顶点的name的值)

gremlin> g.V(1).out().values('name')

==>lop

==>vadas

==>josh

(2).返回相同的数据使用map的方式

gremlin> g.V(1).out().map {it.get().value('name')}

==>lop

==>vadas

==>josh

2. has has的用法类似于过滤器的作用

(1).查找所有顶点中label边的值为person的(默认返回节点信息)

gremlin> g.V().hasLabel('person')

==>v[1]

==>v[2]

==>v[4]

==>v[6]

(2).使用过滤器filter的方式查找

gremlin> g.V().filter {it.get().label() == 'person'}

==>v[1]

==>v[2]

==>v[4]

==>v[6]
3. 进入sideEffect() 的任何内容都被传递到下一个步骤,但可能会发生一些中间过程。

gremlin> g.V().hasLabel('person').sideEffect(System.out.&println)

v[1]

==>v[1]

v[2]

==>v[2]

v[4]

==>v[4]

v[6]

==>v[6]

4.choose()和branch()

解释:返回顶点的姓名,如果姓名为marko则返回年龄,其他的返回姓名。

gremlin> g.V().branch(values('name')).option('marko', values('age')).option(none, values('name'))

==>29

==>vadas

==>lop

==>josh

==>ripple

==>peter

gremlin> g.V().choose(has('name','marko'),values('age'),values('name'))

==>29

==>vadas

==>lop

==>josh

==>ripple

==>peter

 

二、AddEdge Step

此部分的主要功能是为已有的图形添加新的边。


1.addE()

例一 以上图为例

解释:第一个顶点命名为a,查找出边为created的点(3),再次查找入边为created的点,并且这个点不是a,添加一条边,边的名称为co-developer,从a发出属性为:year,2009.

gremlin> g.V(1).as('a').out('created').in('created').where(neq('a')).addE('co-developer').from('a').property('year',2009)

==>e[12][1-co-developer->4]

==>e[13][1-co-developer->6]

2.addE()

例二 

gremlin> g.V(3,4,5).aggregate('x').has('name','josh').as('a').select('x').unfold().hasLabel('software').addE('createdBy').to('a')

==>e[14][3-createdBy->4]

==>e[15][5-createdBy->4]

3.addE()

例三

解释:所有顶点为a,查找出边为created的顶点(3),增加边名称为createdBy,新增的边出点为a,属性名为acl,public。

gremlin> g.V().as('a').out('created').addE('createdBy').to('a').property('acl','public')

==>e[16][3-createdBy->1]

==>e[17][5-createdBy->4]

==>e[18][3-createdBy->4]

==>e[19][3-createdBy->6]

4.addE()

例四 

gremlin> g.V(1).as('a').out('knows').addE('livesNear').from('a').property('year',2009).inV().inE('livesNear').values('year')

==>2009

==>2009

5.addE()

例五 

gremlin> g.V().match(__.as('a').out('knows').as('b'),__.as('a').out('created').as('c'),__.as('b').out('created').as('c')).addE('friendlyCollaborator').from('a').to('b').property(id,13).property('project',select('c').values('name'))

==>e[13][1-friendlyCollaborator->4]

 

三、AddVertex Step

这个过程是用户给图形增加顶点,对于每一个传入对象,都创建一个顶点。此外,GraveTraceSaleStand维护了一个addV()方法。

1.例一 新增一个顶点person,属性为name=stephen。

gremlin> g.addV('person').property('name','stephen')

==>v[12]

2.例二 查看所有顶点的name

gremlin> g.V().values('name')

==>marko

==>vadas

==>lop

==>josh

==>ripple

==>peter

==>stephen

3.例三 所有顶点出边为knows,新增顶点,属性名为name=nothing。

gremlin> g.V().outE('knows').addV().property('name','nothing')

==>v[14]

==>v[16]

4.例四 查看所有顶点中name=nothing的id

gremlin> g.V().has('name','nothing')

==>v[16]

==>v[14]

 

四、AddProperty Step

addProperty()用户给图中的对象增加属性。不同于addV()和addE()

1.例一 给顶点1创建属性country=usa

gremlin> g.V(1).property('country','usa')

==>v[1]

2.例二 给顶点1创建属性city=sanfa fe,state=new mexico并返回所有属性名。

gremlin> g.V(1).property('city','santa fe').property('state','new mexico').valueMap()

==>[country:[usa], city:[santa fe], name:[marko], state:[new mexico], age:[29]]

3.例三 给顶点1创建属性age=35

gremlin> g.V(1).property(list,'age',35)

==>v[1]

4.例四 返回顶点1的所有属性值

gremlin> g.V(1).valueMap()

==>[country:[usa], city:[santa fe], name:[marko], state:[new mexico], age:[29, 35]]

5.例五 给顶点1增加属性friendWeight输出边为knows的值为weight之和,属性为ac=private

gremlin> g.V(1).property('friendWeight',outE('knows').values('weight').sum(),'acl','private')

==>v[1]

6.例六 查询顶点1的friendWeight的属性。

gremlin> g.V(1).properties('friendWeight').valueMap()

==>[acl:private]

 

五、Aggregate Step

aggregte()用于遍历所有特定的对象集合在一起。

1.例一

查找顶点1输出边是created的点(3)
gremlin> g.V(1).out('created')

==>v[3]

将所有顶点1输出边为created的顶点聚合为x

gremlin> g.V(1).out('created').aggregate('x')

==>v[3]

查找所有顶点1输出边为created的顶点(3),再查找输入边为created的所有顶点

gremlin> g.V(1).out('created').aggregate('x').in('created')

==>v[1]

==>v[4]

==>v[6]

查找所有顶点1输出边为created的顶点(3),再查找输入边为created的所有顶点,再查找输出边为created的顶点

gremlin> g.V(1).out('created').aggregate('x').in('created').out('created')

==>v[3]

==>v[5]

==>v[3]

==>v[3]

查找所有顶点1输出边为created的顶点(3),再查找输入边为created的所有顶点,再查找输出边为created的顶点。过滤所有x(x = 顶点1输出边为created的顶点 = 3)的集合并输出name值。

gremlin> g.V(1).out('created').aggregate('x').in('created').out('created').where(without('x')).values('name')

==>ripple

 

六、And Step

and()同时满足and()要求的条件并输出。

1.例一 满足两个条件1.g.V().outE('knows') 2.g.V().values('age').is(lt(30))的名字

gremlin> g.V().and(outE('knows'),values('age').is(lt(30))).values('name')

==>marko

 

七、As Step

as(),是一步虚拟的操作,类似于by()和option().

1.例一 所有顶点命名为a,输出边为created的顶点命名为b,查询a和b。

gremlin> g.V().as('a').out('created').as('b').select('a','b')

==>[a:v[1], b:v[3]]

==>[a:v[4], b:v[5]]

==>[a:v[4], b:v[3]]

==>[a:v[6], b:v[3]]

 

八、By Step

by(),是一步虚拟的操作,一般用于通过条件分组查询。

1.例一 查询所有顶点,通过边的数量分组查询数量

gremlin> g.V().group().by(bothE().count())

==>[1:[v[2], v[5], v[6]], 3:[v[1], v[3], v[4]]]

2.例二 查询所有顶点,通过边的数量分组查询姓名

gremlin> g.V().group().by(bothE().count()).by('name')

==>[1:[vadas, ripple, peteby(),是一步虚拟的操作,一般用于通过条件分组查询。, lop, josh]]

3.例三 查询所有顶点,通过边的数量分组查询每组的数量

gremlin> g.V().group().by(bothE().count()).by(count())

==>[1:3, 3:3]

 

九、Cap Step

 

十、Coalesce Step

 

十一、Count Step

count(),统计遍历总数。

1.例一 统计所有顶点的总数

gremlin> g.V().count()

==>6

2.例二 统计所有顶点中label为person的总数

gremlin> g.V().hasLabel('person').count()

==>4

3.例三 查询顶点label值为person的输出边为created的数量,返回查询路径。

gremlin> g.V().hasLabel('person').outE('created').count().path()

==>[4]

4.例四 查询顶点label值为person的输出边为created的数量,遍历其内容 乘10返回路径。

gremlin> g.V().hasLabel('person').outE('created').count().map {it.get() * 10}.path()

==>[4, 40]

 

十二、Choose Step

choose()步骤,类似于if-else的步骤,判断条件走不同的路径。

1.例一 查找所有顶点中label为person的顶点,如果属性age小于30,查找入边的顶点,否则查找出边的顶点。

(顶点1age小于30没有入边无结果,顶点4age大于30查找出边顶点为3:name=lop和5:name=ripple)

gremlin> g.V().hasLabel('person').choose(values('age').is(lte(30)),__.in(),__.out()).values('name')

==>marko

==>ripple

==>lop

==>lop

2.例二 查找所有顶点中label为person的顶点,如果age为27则输出该顶点的入边顶点,如果age为32则输出该顶点的出边顶点。

(顶点2age为27,入边的顶点为1:name=marko,顶点4age为32,出边的顶点为3:name=lop,5:name=ripple)

gremlin>g.V().hasLabel('person').choose(values('age')).option(27,__.in()).option(32,__.out()).values('name')

==>marko

==>ripple

==>lop

 

十三、Coin Step

 

十四、Constant Step

constant()步骤,定义成常量。

1.例一 查询所有顶点,如果label名为person则返回名字,否则返回常量名为inhuman。

gremlin> g.V().choose(hasLabel('person'),values('name'),constant('inhuman'))

==>marko

==>vadas

==>inhuman

==>josh

==>inhuman

==>peter

 

十五、CyclicPath Step

 

十六、Dedup Step

dedup()步骤,过滤重复数据。

1. 例一 查询所有名为lang的顶点。dedup()过滤到重复的数据。

gremlin> g.V().values('lang')

==>java

==>java

gremlin> g.V().values('lang').dedup()

==>java

 

十七、Drop Step

drop()步骤,删除指定的元素或属性。

1. 例一 查询所有顶点中属性名为name并删除,遍历查询所有的顶点(name的属性已被删除)

gremlin> g.V().properties('name').drop()

gremlin> g.V().valueMap()

==>[age:[29]]

==>[age:[27]]

==>[lang:[java]]

==>[age:[32]]

==>[lang:[java]]

==>[age:[35]]

2.例二 查询并删除所有顶点(查询最后结果为空)

gremlin> g.V().drop()

gremlin> g.V()

 

十八、Explain Step

好像是用来解释的,没什么实质的作用

 

十九、Fold Step

fold()遍历所有的对象,并把他们聚合在一起。

1. 例一:查询顶点1出边为knows的name值,fold()聚合在一起为一个数组。

gremlin> g.V(1).out('knows').values('name')

==>vadas

==>josh

gremlin> g.V(1).out('knows').values('name').fold()

==>[vadas, josh]

 

二十、Graph Step

V()步骤通常用于启动一个图形遍历,但也可以用于中间遍历。

1.例一 查找所有顶点name为marko,vadas或josh命名为person,再次查询所有顶点中name为lop或ripple,增加名为uses的边,从person发出。

gremlin> g.V().has('name', within('marko', 'vadas', 'josh')).as('person').V().has('name', within('lop', 'ripple')).addE('uses').from('person')

==>e[12][1-uses->3]

==>e[13][1-uses->5]

==>e[14][2-uses->3]

==>e[15][2-uses->5]

==>e[16][4-uses->3]

==>e[17][4-uses->5]

 

二十一、Group Step

group()步骤主要用于分组。

1.例一 通过顶点的label值对顶点进行分类

gremlin> g.V().group().by(label)

==>[software:[v[3], v[5]], person:[v[1], v[2], v[4], v[6]]]

2.例二 通过顶点的label值对顶点进行分类,获得他们的姓名。

gremlin> g.V().group().by(label).by('name')

==>[software:[lop, ripple], person:[marko, vadas, josh, peter]]

3.例三 通过顶点的label数量进行分类。

gremlin> g.V().group().by(label).by(count())

==>[software:2, person:4]

 

二十二、GroupCount Step

groupCount()步骤主要用于统计分组后的数量。

1.例一 通过顶点的label值对顶点进行分类

主要用于统计分组

1.例一 查询顶点label为person的年龄分布情况。

gremlin> g.V().hasLabel('person').values('age').groupCount()

==>[32:1, 35:1, 27:1, 29:1]

2.例二 同例一

gremlin> g.V().hasLabel('person').groupCount().by('age')

==>[32:1, 35:1, 27:1, 29:1]

 

二十三、Has Step

has() 作用可以过滤顶点,过滤边以及过滤属性。

例如:

    has(key,value): 删除没有提供的键值对属性。

    has(key,predicate): 删除没有提供的键值。

    hasLabel(labels...): 删除没有对应label属性的内容。

    hasId(ids...): 删除没有对应id属性的内容。

    has(key): 删除没有该健的值的内容。

    hasNot(key): 删除有对应健的内容。

    has(key, traversal)  : 遍历没有结果的则删除。

1.例一 查询所有顶点中label为person的顶点。

gremlin> g.V().hasLabel('person')

==>v[1]

==>v[2]

==>v[4]

==>v[6]

2.例二 查询所有顶点中label为person的输出的顶点,并且name=vadas或josh。

gremlin> g.V().hasLabel('person').out().has('name',within('vadas','josh'))

==>v[2]

==>v[4]

3.例三 查询所有顶点中label为person的输出的顶点,并且name=vadas或josh,输出边label为created的边。

gremlin> g.V().hasLabel('person').out().has('name',within('vadas','josh')).outE().hasLabel('created')

==>e[10][4-created->5]

==>e[11][4-created->3]

4.例四 查询所有顶点中年龄在20~30之间的。

gremlin> g.V().has('age',inside(20,30)).values('age')

==>29

==>27

5.例五 查询所有顶点中年龄不在20~30之间的。

gremlin> g.V().has('age',outside(20,30)).values('age')

==>32

==>35

6.例六 查询所有顶点中姓名为josh和marko的并遍历属性。

gremlin> g.V().has('name',within('josh','marko')).valueMap()

==>[name:[marko], age:[29]]

==>[name:[josh], age:[32]]

7.例七 查询所有顶点中姓名不为josh和marko的并遍历属性。

gremlin> g.V().has('name',without('josh','marko')).valueMap()

==>[name:[vadas], age:[27]]

==>[name:[lop], lang:[java]]

==>[name:[ripple], lang:[java]]

==>[name:[peter], age:[35]]

8.例八 查询所有顶点中姓名不为josh和marko的并遍历属性。

gremlin> g.V().has('name',not(within('josh','marko'))).valueMap()

==>[name:[vadas], age:[27]]

==>[name:[lop], lang:[java]]

==>[name:[ripple], lang:[java]]

==>[name:[peter], age:[35]]

 

二十五、Is Step

is()类似于等于的作用。

1.例一 查询所有顶点中age=32的顶点。

gremlin> g.V().values('age').is(32)

==>32

2.例二 查询所有顶点中age<30的顶点。

gremlin> g.V().values('age').is(lte(30))

==>29

==>27

3.例三 查询所有顶点中age在30到40之间的顶点。

gremlin> g.V().values('age').is(inside(30, 40))

==>32

==>35

4.例四 查询所有顶点,条件为入边为created并且数量为1,显示name。

gremlin> g.V().where(__.in('created').count().is(1)).values('name')

==>ripple

5.例五 查询所有顶点,条件为入边为created并且数量大于2,显示name。

gremlin> g.V().where(__.in('created').count().is(gte(2))).values('name')

==>lop

6.例六 查询所有顶点,平均值在30到35之间。

gremlin> g.V().where(__.in('created').values('age').mean().is(inside(30d, 35d))).values('name')

==>lop

==>ripple

 

二十六、Limit Step

Limit()的主要作用和Range()类似,主要用于限制最小条数。

1.例一 查询所有顶点的前两条。

gremlin> g.V().limit(2)

==>v[1]

==>v[2]

 

二十七、Local Step

 

二十八、Match Step

 

二十九、Max Step

Max()的作用查找流中最大的值

1.例一 两种方式查找age最大的值。

gremlin> g.V().values('age').max()

==>35

gremlin> g.V().repeat(both()).times(3).values('age').max()

==>35

 

三十、Mean Step

mean()的主要作用用于求平均值。

1.例一 查询所有顶点的平均值

gremlin> g.V().values('age').mean()

==>30.75

2.例二 查询所有顶点,查询三次所有边,计算年龄的平均值

gremlin> g.V().repeat(both()).times(3).values('age').mean()

==>30.645833333333332

3.例三 查询所有顶点,查询三次所有去重边,计算年龄的平均值

gremlin> g.V().repeat(both()).times(3).values('age').dedup().mean()

==>30.75

 

三十一、Min Step

Min()的作用查找流中最小的值

1.例一 两种方式查找age最小的值。

gremlin> g.V().values('age').min()

==>27

gremlin> g.V().repeat(both()).times(3).values('age').min()

==>27

 

三十二、Or Step

or()或者的作用满足条件之一即可返回数据

1.例一 查找顶点的输出边为created或者输入边为created的数量大于1.

gremlin> g.V().or(__.outE('created'),__.inE('created').count().is(gt(1))).values('name')

==>marko

==>lop

==>josh

==>peter

 

三十三、Order Step

order()当需要对遍历流的对象进行排序时,可以利用Order()

1.例一 查询顶点的姓名并进行排序

gremlin> g.V().values('name').order()

==>josh

==>lop

==>marko

==>peter

==>ripple

==>vadas

2.例二 查询顶点的姓名并进行倒序排序

gremlin> g.V().values('name').order().by(decr)

==>vadas

==>ripple

==>peter

==>marko

==>lop

==>josh

3.例三 查询label为person的顶点,并使用age进行升序排序,显示其姓名。

gremlin> g.V().hasLabel('person').order().by('age', incr).values('name')

==>vadas

==>marko

==>josh

==>peter

 

三十四、Path Step


path()的作用主要用于查询每一步的路径。

1.例一 查询顶点输出顶点的输出顶点的姓名。

gremlin> g.V().out().out().values('name')

==>ripple

==>lop

1.例一 查询顶点输出顶点的输出顶点的姓名的路径。

gremlin> g.V().out().out().values('name').path()

==>[v[1], v[4], v[5], ripple]

==>[v[1], v[4], v[3], lop]

2.例二 如果边缘在路径中是必须的。

gremlin> g.V().outE().inV().outE().inV().path()

==>[v[1], e[8][1-knows->4], v[4], e[10][4-created->5], v[5]]

==>[v[1], e[8][1-knows->4], v[4], e[11][4-created->3], v[3]]

3.例三 如果by()在路径中是必须的。

gremlin> g.V().out().out().path().by('name').by('age')

==>[marko, 32, ripple]

==>[marko, 32, lop]

 

三十五、Profile Step

允许配置遍历的信息等。

 

三十六、Range Step

range()的主要作用是限制查询的条数

1.例一 查找所有顶点从下标1的开始查询3条。

gremlin> g.V().range(1,3)

==>v[2]

==>v[3]

 

三十七、Repeat Step

repeat()用于对给定的条件 进行循环。

1.例一 查询顶点1的输出顶点的路径循环两次,并显示其名字。

gremlin> g.V(1).repeat(out()).times(2).path().by('name')

==>[marko, josh, ripple]

==>[marko, josh, lop]

2.例二 查询所有顶点输出的顶点路径,显示名字,直到name=ripple时停止。

gremlin> g.V().until(has('name','ripple')).repeat(out()).path().by('name')

==>[marko, josh, ripple]

==>[josh, ripple]

==>[ripple]

 

三十八、Sack Step

 

三十九、Select Step

select()查询过滤需要显示的内容

1.例一 所有的顶点为a,输出的顶点为b,再次输出的顶点为c,查询a,b,c。

gremlin> g.V().as('a').out().as('b').out().as('c').select('a','b','c')

==>[a:v[1], b:v[4], c:v[5]]

==>[a:v[1], b:v[4], c:v[3]]

2.例二 所有的顶点为a,输出的顶点为b,再次输出的顶点为c,查询a,b。

gremlin> g.V().as('a').out().as('b').out().as('c').select('a','b')

==>[a:v[1], b:v[4]]

==>[a:v[1], b:v[4]]

3.例三 所有的顶点为a,输出的顶点为b,再次输出的顶点为c,查询a,b并返回姓名。

gremlin> g.V().as('a').out().as('b').out().as('c').select('a','b').by('name')

==>[a:marko, b:josh]

==>[a:marko, b:josh]

 

四十、SimplePath Step

simplePath()作用为过滤重复路径。

1.例一 查询顶点1的所有相邻顶点(2,3,4),再次查询相邻的顶点(1,1,4,6,3,5,1)

gremlin> g.V(1).both().both()

==>v[1]

==>v[4]

==>v[6]

==>v[1]

==>v[5]

==>v[3]

==>v[1]

2.例二 查询顶点1的所有相邻顶点(2,3,4),再次查询相邻的顶点(1,1,4,6,3,5,1),过滤重复路径。

gremlin> g.V(1).both().both().simplePath()

==>v[4]

==>v[6]

==>v[5]

==>v[3]

3.例三 查询顶点1的所有相邻顶点(2,3,4),再次查询相邻的顶点(1,1,4,6,3,5,1),过滤重复路径的路径查看。

gremlin> g.V(1).both().both().simplePath().path()

==>[v[1], v[3], v[4]]

==>[v[1], v[3], v[6]]

==>[v[1], v[4], v[5]]

==>[v[1], v[4], v[3]]

 

四十一、Store Step

 

四十二、Subgraph Step

用于提取一部分子图用于分析。

 

四十三、Sum Step

sum()作用查询条件的总和

1.例一 查询所有顶点中age的总和

gremlin> g.V().values('age').sum()

==>123

2.例二 查询所有顶点中所有边的时间的年龄之和

gremlin> g.V().repeat(both()).times(3).values('age').sum()

==>1471

 

四十四、Tail Step

tail()类似于limit()倒着获取结果集的内容。

1.例一 获取顶点中最后一条记录的名称。

gremlin> g.V().values('name').order().tail()

==>vadas

2.例二 获取顶点中最后一条记录的名称。

gremlin> g.V().values('name').order().tail(1)

==>vadas

3.例三 获取顶点中倒数三条记录的名称。

gremlin> g.V().values('name').order().tail(3)

==>peter

==>ripple

==>vadas

 

四十五、TimeLimit Step

 

四十六、Tree Step

 

四十七、Unfold Step

unfold()是fold()的反向形式,将放入数组的内容拆分出来。

1.例一 查询顶点1的输出顶点的集合,并增加gremlin和[1.23,2.34]的内容。

gremlin> g.V(1).out().fold().inject('gremlin',[1.23,2.34])

==>gremlin

==>[1.23, 2.34]

==>[v[3], v[2], v[4]]

2.例二 查询顶点1的输出顶点的集合,并增加gremlin和[1.23,2.34]的内容拆分出来。

gremlin> g.V(1).out().fold().inject('gremlin',[1.23,2.34]).unfold()

==>gremlin

==>1.23

==>2.34

==>v[3]

==>v[2]

==>v[4]

 

四十八、Union Step

union()支持任意数量的遍历结果的合并的结果集。

1.例一 查询顶点4的入点的年龄值和出点的lang值。

gremlin> g.V(4).union(__.in().values('age'),out().values('lang'))

==>29

==>java

==>java

2.例二 查询顶点4的入点的年龄值和出点的lang值的路径。

gremlin> g.V(4).union(__.in().values('age'),out().values('lang')).path()

==>[v[4], v[1], 29]

==>[v[4], v[5], java]

==>[v[4], v[3], java]

 

四十九、ValueMap Step

valueMap()映射元素的属性表示。

1.例一 查询所有顶点的属性。

gremlin> g.V().valueMap()

==>[name:[marko], age:[29]]

==>[name:[vadas], age:[27]]

==>[name:[lop], lang:[java]]

==>[name:[josh], age:[32]]

==>[name:[ripple], lang:[java]]

==>[name:[peter], age:[35]]

2.例二 查询所有顶点的属性age的结果。

gremlin> g.V().valueMap('age')

==>[age:[29]]

==>[age:[27]]

==>[:]

==>[age:[32]]

==>[:]

==>[age:[35]]

3.例三 查询顶点的属性为age和blah的结果集。

gremlin> g.V().valueMap('age','blah')

==>[age:[29]]

==>[age:[27]]

==>[:]

==>[age:[32]]

==>[:]

==>[age:[35]]

4.例四 查询所有边的属性值。

gremlin> g.E().valueMap()

==>[weight:0.5]

==>[weight:1.0]

==>[weight:0.4]

==>[weight:1.0]

==>[weight:0.4]

==>[weight:0.2]

 

五十、Vertex Step

点是gremlin的基础。通过这些步骤,它可以在图“-”即“遍历”上“移动”。

    out(string...): 移动到边缘标签输出的相邻顶点。

    in(string...): 移动到边缘标签输出的相邻顶点。

    both(string...): 移动到两个传入和传出相邻顶点给边缘标签。

 

        outE(string...): 移动到输出的边上。

        inE(string...): 移动到输入的边上。

        bothE(string...): 移动到输出和输入边上。

//与out()的区别在于out()以顶点为基准,而outV()以边为基准

    outV(): 移动到输出的顶点上。

    inV(): 移动到输入的顶点上。

    bothV(): 移动到输出和输入的顶点上。

    otherV() : 移动到不是被移动的顶点的顶点。

1.查询顶点4的边中为know,created和blah的边上。

gremlin> g.V(4).bothE('knows','created','blah')

==>e[10][4-created->5]

==>e[11][4-created->3]

==>e[8][1-knows->4]

2.查询顶点4的边中为know,created和blah的边上其余点上。

gremlin> g.V(4).bothE('knows','created','blah').otherV()

==>v[5]

==>v[3]

==>v[1]

 

五十一、Where Step

where()主要用于过滤条件的工作。

1.例一 顶点1命名为a,查找输出边为created的顶点,再次查找输入边为created的顶点,返回出去a的顶点。

gremlin> g.V(1).as('a').out('created').in('created').where(neq('a'))

==>v[4]

==>v[6]

2.例二 没理解withSideEffect的意思

gremlin> g.withSideEffect('a',['josh','peter']).V(1).out('created').in('created').values('name').where(within('a'))

==>josh

==>peter

3.例三 查询顶点1输出边为created的顶点,再次查找输入边为created的顶点,返回最后查找出来顶点的输出边为created的数量大于1的name。

gremlin> g.V(1).out('created').in('created').where(out('created').count().is(gt(1))).values('name')

==>josh

 

五十二、Inject Step

Inject()插入的作用,使得可以任意地将对象插入到遍历流中。

1.例一 查询第四个顶点的输出顶点的姓名,并插入一个姓名为daniel。

gremlin> g.V(4).out().values('name').inject('daniel')

==>daniel

==>ripple

==>lop

2.例二 询第四个顶点的输出顶点的姓名,并插入一个姓名为daniel。map遍历每个元素的长度。

gremlin> g.V(4).out().values('name').inject('daniel').map {it.get().length()}

==>6

==>6

==>3

3.例三 询第四个顶点的输出顶点的姓名,并插入一个姓名为daniel。map遍历每个元素的长度的路径。

gremlin> g.V(4).out().values('name').inject('daniel').map {it.get().length()}.path()

==>[daniel, 6]

==>[v[4], v[5], ripple, 6]

==>[v[4], v[3], lop, 3]

 

五十三、Sample Step

sample 查询一些有用的遍历信息

1.例一 查询顶点输出边的weight值.

gremlin> g.V().outE().sample(1).values('weight')

==>0.4

2.例二 查询顶点输出边的weight值,通过weight返回一个结果.

gremlin> g.V().outE().sample(1).by('weight').values('weight')

==>1.0

3.例三 查询顶点输出边的weight值,通过weight返回两个结果.

gremlin> g.V().outE().sample(2).by('weight').values('weight')

==>1.0

==>0.5


 

<think>我们正在处理用户的问题:如何在使用Gremlin查询语言时,将数组作为属性保存到图数据库中。根据Gremlin的规范,属性值可以是基本数据类型(如String、Integer等),也可以是集合类型(如List、Set)。但是,不同的图数据库实现可能对集合类型的支持有所不同。用户提到的是JanusGraph(从引用[1]中可以看出用户使用了JanusGraph),而JanusGraph支持多值属性(multi-properties)和属性列表(list properties)。不过,需要注意的是,JanusGraph的多值属性默认是Set(无序且不重复),如果需要有序或允许重复,则需要使用cardinality设置为list。步骤:1.在定义属性时,指定cardinality为list(如果需要有序且允许重复)或set(如果不需要重复且无序)。2.使用addProperty或property方法添加属性,注意使用正确的cardinality。示例:假设我们有一个顶点,我们想为其添加一个标签(label)为“person”的顶点,并为其添加一个名为“hobbies”的属性,该属性是一个数组(即多个值)。在Gremlin中,我们可以这样做:-首先,创建顶点并指定id(或让系统自动生成):g.addV('person').property(list, 'hobbies', 'reading').property(list, 'hobbies', 'sports')注意:这里使用了`list`作为cardinality,表示这个属性可以有多个值,且以列表形式存储(有序,允许重复)。如果使用`set`,则不允许重复且无序。另一种方式是先创建顶点,然后逐步添加属性:v= g.addV('person').next()v.property(list, 'hobbies', 'reading')v.property(list, 'hobbies', 'sports')但是,在Gremlin控制台中,我们通常使用链式调用,因此第一种方式更常见。另外,如果属性已经存在,并且我们想一次性设置整个数组,我们可以这样做:g.V().has('person', 'name','Alice').property(list, 'hobbies', ['reading','sports'])但是,请注意,直接传递一个数组给property方法可能不会被所有版本的Gremlin支持。在JanusGraph中,我们可以使用这种方式,但实际上它会将数组作为一个单值存储(即一个属性值是一个数组),这通常不是我们想要的。我们想要的是多个独立的属性值(每个值都是独立的,但共享同一个key)。因此,正确的做法是使用多个property步骤,或者使用unfold来展开数组。例如,如果我们有一个数组,我们可以这样做:hobbies= ['reading','sports']g.V().has('person', 'name','Alice').sideEffect{it.get().properties('hobbies').remove()//删除现有的hobbies属性(如果需要重置)}.iterate()//注意:这里需要先执行删除,然后再添加,但是这样写可能不高效,仅作示例//然后添加新的属性值hobbies.each{ hobby->g.V().has('person', 'name','Alice').property(list,'hobbies',hobby).next()}但是,这种方式需要多次查询,效率不高。我们可以使用一个更高效的方式,使用一个遍历:g.V().has('person','name', 'Alice').as('p').sideEffect{//删除现有的hobbies属性(可选,如果需要重置)it.get().properties('hobbies').remove()}.fold().unfold().//这里只是为了确保继续流inject(hobbies).unfold().as('hobby').addE('someEdge').from('p').to('p')//这步显然不对,我们不是要加边实际上,我们可以不用删除,而是直接覆盖。但是,覆盖属性在Gremlin中不是原子操作,所以我们需要小心。另一种方法是:使用一个循环来添加每个值。在Gremlin中,我们可以这样一次性添加多个值(使用union或coalesce等步骤):g.V().has('person','name', 'Alice').property(list, 'hobbies', 'reading').property(list, 'hobbies', 'sports').iterate()或者,如果我们有一个数组变量,我们可以使用unfold来展开数组并逐个添加:hobbies= ['reading','sports','reading']//允许重复g.V().has('person', 'name','Alice').fold().//将顶点折叠成一个列表(只有一个元素)coalesce(unfold(),//再展开,这样我们就可以对同一个顶点多次操作constant(hobbies).unfold().//将数组展开成多个值property(list, 'hobbies', it.get())//但是这里不能直接这样写,因为property需要作用在顶点上)上述写法可能不工作。更好的方式是:g.V().has('person', 'name','Alice').sideEffect{v->hobbies.each{ hobby->v.property(list, 'hobbies', hobby)}}在Gremlin控制台中,我们可以使用闭包(Groovy)来实现,但如果是纯Gremlin(不依赖特定语言),我们可以这样:g.V().has('person', 'name','Alice').property(list, 'hobbies', 'reading').property(list, 'hobbies', 'sports').所以,如果数组是动态的,我们可能需要使用编程语言(如Groovy)来构建查询。总结:在Gremlin中,将数组作为属性(多值属性)保存,需要指定cardinality(如list或set),然后为每个值添加一个property。另外,在JanusGraph中,我们可以在定义属性key时指定cardinality,这样在添加属性时就不需要每次都指定。例如,在schema中定义:mgmt= graph.openManagement()hobby =mgmt.makePropertyKey('hobbies').dataType(String.class).cardinality(Cardinality.LIST).make()mgmt.commit()这样,在添加属性时,我们可以直接使用:g.addV('person').property('hobbies', 'reading').property('hobbies','sports')因为cardinality已经在schema中定义为LIST,所以property步骤会自动按照LIST的方式添加。因此,推荐的做法是:在schema中定义属性时指定cardinality,然后就可以直接添加多个值了。如果用户还没有定义schema,那么需要先定义。如果不定义,JanusGraph默认使用Cardinality.SINGLE,即每个key只能有一个值(后设置的会覆盖前一个)。所以,步骤:1.确保属性key的cardinality是LIST(或SET,根据需求)。2.使用多个property步骤添加每个值。示例(在Gremlin控制台中):假设我们还没有定义schema,我们可以先定义::remoteconnect tinkerpop.server conf/remote.yaml:remoteconsolegraph= JanusGraphFactory.open("conf/janusgraph-cql.properties")mgmt= graph.openManagement()if(mgmt.getPropertyKey('hobbies')== null) {hobby= mgmt.makePropertyKey('hobbies').dataType(String.class).cardinality(Cardinality.LIST).make()}mgmt.commit()然后添加顶点:g=graph.traversal()g.addV('person').property('name','Alice').property('hobbies','reading').property('hobbies','sports').iterate()查询验证:g.V().has('person','name','Alice').properties('hobbies')应该会返回两个属性值:reading和sports。注意:在Gremlin中,我们也可以使用`property`步骤一次添加多个值,但需要以多值的形式,例如:g.addV('person').property('hobbies','reading','sports')//这是错误的,property方法只能接受一个值所以,必须分开写。另外,如果使用Java等编程语言,我们可以循环添加。因此,针对用户的问题,我们给出以下步骤:1.确保属性在schema中定义为LIST(或SET)类型(如果需要多值)。2.使用多个property步骤,每个步骤添加数组中的一个元素。如果用户想一次添加整个数组,可以使用脚本(如Groovy)来循环,或者使用unfold(但需要结合其他步骤,可能比较复杂)。在Gremlin中,没有直接传递数组作为多值属性的语法,必须将数组展开为多个值。因此,我们给出以下示例代码:示例1:在Gremlin控制台中,手动添加多个值g.addV('person').property('name','Alice').property('hobbies','reading').property('hobbies','sports')示例2:如果有一个数组变量,使用Groovy循环hobbies= ['reading','sports']v= g.addV('person').property('name','Alice').next()hobbies.each{ hobby->g.V(v).property(list, 'hobbies', hobby).iterate()//注意:如果schema中已经定义了cardinality,则不需要写list,直接写'hobbies'}但是,如果用户是在应用程序中,那么取决于使用的语言(如Java),可以使用循环。另外,注意:在JanusGraph0.5.0及以上版本,支持直接使用List作为值,但是需要确保属性的cardinality是LIST。例如:g.addV('person').property('hobbies', ['reading','sports'])实际上,在JanusGraph0.5.x中,这样写会被解释为添加一个属性值(这个值是一个List),而不是多个属性值。所以,不推荐这样写。因此,我们建议使用多个property步骤。最后,我们给出一个完整的示例(假设schema已经定义好):g.addV('person').property('name','Alice').property('hobbies','reading').property('hobbies','sports').iterate()或者,使用一个循环(在Groovy中):defhobbies =['reading','sports','hiking']g.addV('person').property('name','Alice').as('v').sideEffect{ hobbies.each{hobby ->g.V('v').property('hobbies',hobby)}}.iterate()但是,上面的sideEffect写法在Gremlin中可能不标准,因为Gremlin的步骤是链式的。更标准的写法可能是:g.addV('person').property('name','Alice').as('v').inject(hobbies).unfold().as('hobby').addV()//这里不能直接添加属性到顶点v,需要另一种方式我们可以这样:g.addV('person').property('name','Alice').as('v').inject(hobbies).unfold().as('hobby').sideEffect(select('v').property('hobbies', select('hobby'))).iterate()但这样写会创建两个顶点?不会,因为addV只创建了一个顶点。这个遍历会:-首先,创建一个顶点,标记为'v'-然后,注入一个数组(hobbies),展开成多个hobby-对于每个hobby,执行sideEffect:选择顶点'v',并添加一个属性所以,最终会添加多个属性到同一个顶点。因此,我们可以推荐这种写法,它在一个遍历中完成。总结:在Gremlin中,将数组保存为属性(多值属性)的方法有两种:1.使用多个property步骤(适用于已知且数量不多的数组)。2.使用inject和unfold结合sideEffect(适用于动态数组)。示例2的完整代码(在Gremlin控制台中):hobbies =['reading','sports','hiking']g.addV('person').property('name','Alice').as('v').inject(hobbies).unfold().as('hobby').sideEffect(select('v').property('hobbies', select('hobby'))).iterate()这样,我们就将数组中的每个元素作为属性'hobbies'的一个值添加到了顶点上。注意:如果属性'hobbies'在schema中没有定义为LIST,那么只有最后一个值会被保留(因为默认是SINGLE)。所以,务必先定义schema。因此,我们建议用户先检查或定义属性key的cardinality。在JanusGraph中,查看属性key的cardinality:mgmt= graph.openManagement()mgmt.getPropertyKey('hobbies').cardinality()如果不存在,则创建。所以,用户的问题解决步骤:1.定义属性key的cardinality为LIST(如果需要有序且允许重复)或SET(如果不需要重复且无序)。2.使用上述方法之一添加属性值。最后,我们生成相关问题。</think>### 在 Gremlin 中将数组保存为图数据库属性 在 Gremlin 中,将数组保存为图数据库属性时,需根据图数据库的实现(如 JanusGraph)选择合适的方法。以下分步骤说明: #### 1. **确认属性基数(Cardinality)** - 图数据库默认属性为**单值**(`Cardinality.SINGLE`),直接保存数组会被视为单个值(如 `["a","b"]` 作为整体存储)。 - 若需存储为**多值属性**(每个元素独立存储),需在 Schema 中定义属性为 `LIST` 或 `SET`: ```groovy // 在 JanusGraph 中定义多值属性 mgmt = graph.openManagement() hobbies = mgmt.makePropertyKey('hobbies') .dataType(String.class) .cardinality(Cardinality.LIST) // 允许重复值 .make() mgmt.commit() ``` #### 2. **保存数组的两种方法** ##### 方法 1:链式添加元素(推荐) ```groovy g.addV('person') .property('name', 'Alice') .property(list, 'hobbies', 'reading') // 显式指定基数 .property(list, 'hobbies', 'sports') .next() ``` - `list` 表示基数(需导入 `org.janusgraph.core.Cardinality`)。 - **结果**:顶点有两个独立的 `hobbies` 属性值:`reading` 和 `sports`。 ##### 方法 2:动态展开数组(Groovy/JVM 语言) ```groovy hobbies_array = ['reading', 'sports'] v = g.addV('person').property('name', 'Alice').next() hobbies_array.each { hobby -> g.V(v).property(list, 'hobbies', hobby).iterate() } ``` #### 3. **验证结果** ```groovy g.V().has('person', 'name', 'Alice') .properties('hobbies') .value() // 输出:reading、sports(两个独立值) ``` #### 注意事项 - **Schema 必需**:未定义多值基数时,数组会被存储为单值字符串(如 `"[reading, sports]"`)[^1]。 - **图数据库差异**: - JanusGraph/OrientDB 支持多值属性。 - Neo4j 需通过关系或序列化(如 JSON)存储数组。 - **性能**:链式添加比循环更高效,减少数据库访问次数。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值