gremlin的查询是流式查询,一步一步的进行下去,当然这里的“一步”可能是一个方法(g.V().has())也可能是多个方法组成的一步(g.V().order().by(desc,‘age’))。下面看一个案例
g.V().has('code','AUS').out().value('name','age').order().by('age',desc)
步骤解读
第一步:g.V() 标明是对图库中的所有节点进行操作的
第二步:has(‘code’,‘AUS’) 获取包含属性code并且该属性的值为AUS的所有节点
第三步:out() 获取上个结果集中所有节点的出边对应的节点
第四步:value(‘name’,‘age’) 获取上个结果集中所有节点的name和age属性值
第五步:order().by(‘age’,desc) 对结果集根据age进行降序排序
从上面便可以看出gremlin流式执行的特征,这使得gremlin的查询语句可以十分的灵活,从而满足我们的各种查询需求。
1:想要了解更多全面的查询方法,可以看英文官网:http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html#_introduction
2:通过看本文章你会对gremlin查询的形式方法有大体的了解,之后找方法在官网就可以了
3:本文章在使用过程会不断更新
graph = TinkerGraph.open()
g = graph.traversal()
在下面的例子中,你会发现几乎每一个查询的开始都会有他们的存在
V()代表查看图中的所有节点,接下来的操作是对节点进行操作的
E()代表图中的所有边,接下来的操作就是对边操作的
g.V().has('code','AUS').out().value('name','age')
//获取AUS的出边对应节点的name和age属性的值
g.V().has('code','AUS').out().value()
//显示所有的属性值
g.V().has('code','AUS')
//获取拥有code属性并且其属性值为AUS的节点
g.V().has('user','code','AUS')
//相当于 g.V().hasLabel('user').has('code','AUS')
g.V().hasNot('name')
//获取所有不包含name属性的节点,等同于g.V().not(has('name'))
g.V().hasLabel("user")
//获取label为user的节点
g.V().has('code','AUS').out('route').has('code','DFW').hasNext()
true
g.V().has('code','AUS').out('route').has('code','SYD').hasNext()
false
g.V().hasLabel('airport').range(0,2)
//输出结果集中1,2个节点
g.V().hasLabel('airport').range(3,6)
//输出结果集中4,5,6个节点
g.V().range(3500,-1)
//输出结果集中3500往后的所有节点
g.V().has('region','US-TX').skip(5)
//跳过节点集中的前5条数据,从第六条开始,效果等同于下面的语句
g.V().has('region','US-TX').range(5,-1)
g.V().has('code','AUS').out().order().by()
g.V().has('code','AUS').out().order(local).
g.V().has('code','AUS').out()
g.V().has('code','AUS').out()
order(local)中local的作用:Notice also how local is used as a parameter to order. This is required so that the ordering is done while the final list is being constructed. If you do not specify local then order will have no effect as it will be applied to the entire result which is treated as a single entity at that point. 这是官网上的一句话,我翻译了一下没太明白,大体的意思我理解的是:加local参数的话会在最终结果生成前就完成排序。。大家可以翻译一下
g.V().has('code','AUS').out()
//获取AUS的节点所有出边对应的节点
g.V().has('code','AUS').out("brought")
//获取AUS节点所有边关系为“brought”的出边对应的节点
g.V().has('code','AUS').in()
//获取AUS的节点所有入边对应的节点
g.V().has('code','AUS').in("brought")
//获取AUS节点所有边关系为“brought”的入边对应的节点
g.V().has('code','AUS').out().count()
//获取AUS节点的出边的个数
g.V().has('code','AUS').out().groupCount().by("name")
//根据结果集的name属性的值进行分组计数,最终结果类似于:[a:1,b:3,r:6]
g.V().has('code','AUS').out().out().dedup().count()
//步骤解读:
1:获取AUS节点的两度出节点,用dedup对结果进行去重
2:使用count()对结果集进行计数
//获取AUS节点的大于两度出度的节点个数,注意应该不包含一度的节点
g.V().has('code','AUS').out().aggregate('nonstop').
out().where(without('nonstop')).dedup().count()
//第一行获取一度的节点并将其结果集存储为一个临时集合命名为"nonstop"
//第二行获取二度节点,并且使用临时集合去除掉一度节点,去重,计数
g.V().hasLabel('airport').values('code').limit(20)
//只显示前20个
g.V().hasLabel('airport').values('code').tail(20)
//只显示最后20个
g.V().has('airport','code','AUS').
repeat(timeLimit(10).out()).until(has('code','LHR')).path().by('code')
//上述作用:获取在10毫秒内查询到的结果
g.V().has('code','AUS').outE().inV().path()
g.V().has('code','AUS').inE().outV().path()
//获取出边或者入边
g.V().has('code','AUS').outE('brought').inV().path()
g.V().has('code','AUS').inE('brought').outV().path()
//获取指定的边关系的出边入边
g.V().has('code','MIA').
outE().as('e').inV().has('code','DFW').
select('e')
//第一步:选择源节点
//第二步:outE找到所有出边as('e')将结果存储为标签e
//第三步:inV().has('code','DFW')找到前面结果集的边入节点为code属性为DFW值得节点
//将边显示出来:结果类似于:
e[4127][16-route->8]
这样就获取到了两个节点之间的边
g.V().has('code','DFW').as('from').out().
has('region','US-CA').as('to').
select('from','to')
//has('code','DFW').as('from') :将has('code','DFW')的结果集标识为from标签的临时结果,下面使用的时候直接使用from即可
//返回的结果类型
[from:v[8],to:v[13]]
[from:v[8],to:v[23]]
[from:v[8],to:v[24]]
g.V().has('type','airport').limit(10).as('a','b','c').
select('a','b','c').
by('code').by('region').by(out().count())
//返回结果为:
[a:ATL,b:US-GA,c:232]
[a:ANC,b:US-AK,c:39]
[a:AUS,b:US-TX,c:59]
g.V().has('type','airport').limit(10).
project('a','b','c').
by('code').by('region').by(out().count())
//效果等同于:只不过上面的写法更加简洁
g.V().has('type','airport').limit(10).as('a','b','c').
select('a','b','c').
by('code').by('region').by(out().count())
//输出结果:
[a:ATL,b:US-GA,c:232]
[a:ANC,b:US-AK,c:39]
[a:AUS,b:US-TX,c:59]
g.V(1).as('a').V(2).as('a').select(first,'a')
v[1]
//选择第一个a标签
g.V(1).as('a').V(2).as('a').select(last,'a')
v[2]
//选择最后一个a标签
g.V(1).as('a').V(2).as('a').select(all,'a')
[v[1],v[2]]
//选择所有a标签
g.V().has('code','AUS').as('a').
out().as('a').limit(10).
select(last,'a').by('code')
g.V().has('code','AUS').as('a').
out().as('a').limit(10).
select(first,'a').by('code')
g.V().has('code','AUS').as('a').
out().as('a').limit(10).
select(all,'a').unfold().values('code')
返回结构:kv对数组,key:属性key,v:属性的值列表(list,这样可以显示该属性对应的多个值)
结构类似于:
[country:[US], code:[AUS], longest:[12248], city:[Austin], elev:[542], icao:[KAUS], lon:[-97.6698989868164], type:[airport], region:[US-TX], runways:[2], lat:[30.1944999694824], desc:[Austin Bergstrom International Airport]]
g.V().has('name','gremlin').valueMap()
//获得节点的所有属性
//valueMap在默认情况下不显示ID和label值,必须添加true参数
g.V().has('name','gremlin').valueMap(true)
//返回的集合中包含ID和label值
g.V().has('code','AUS').valueMap(true,'region')
//返回id+label+region三个属性的kv
g.E(5161).valueMap(true)
//返回id为5161边的属性
为了完整起见,还可以使用select来优化valueMap的结果
g.V().has('code','AUS').valueMap().select('code','icao','desc')
//返回的结果为 code+icao+desc属性的kv
如果想要结果集合更容易展现,可以使用unfold方法将其展开,但是结果的结构就变了,只是为了在 console上更加容易看
g.V().has('code','AUS').valueMap(true,'code','icao','desc','city').unfold()
//输出结果形式:
code=[AUS]
city=[Austin]
icao=[KAUS]
id=3
label=airport
desc=[Austin Bergstrom International Airport]
listr = g.V().has('airport','region','US-TX').
values('runways').toList().join(',')
//此处的join(',')是将结果组合起来,用逗号分割,这样最终的结果就是一个字符串
//输出结果:
2,7,5,3,4,3,3,3,3,4,2,3,2,3,2,2,3,2,1,3,2,3,4,3,4,2
//在我们项目中使用一般不会加join,因为最终结果只会是一个字符串
listr = g.V().has('airport','region','US-TX').
values('runways').toList()
//使用集合的一些操作:
-> listr[1]
7
-> listr.size()
26
-> listr[1,3]
7
3
setr = g.V().has('airport','region','US-TX').
values('runways').toSet().join(',')
//输出结果:
1,2,3,4,5,7
setb= g.V().has('airport','region','US-TX')
.values('runways').toBulkSet().join(',')
//输出结果:
2,2,2,2,2,2,2,2,7,5,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,1
//不使用join
setb= g.V().has('airport','region','US-TX').values('runways').toBulkSet()
//一些操作
setb.uniqueSize()
6
setb.size()
26
setb.asBulk()
2=8
7=1
5=1
3=11
4=4
1=1
//案例一:
a = []
g.V().has('airport','region','US-TX').values('runways').fill(a)
//操作
a.size()
26
a[1,3]
73
//案例二:
s = [] as Setg.V().has('airport','region','US-TX').values('runways').fill(s)
//操作
println s
[2, 7, 5, 3, 4, 1]
未完待续。。。。
private GraphTraversal createGraphTraversalByIdLabel(String id,String label,Map<String,Object> propertys){
GraphTraversal graphTraversal = null;
if(StringUtils.isNotEmpty(id)){
graphTraversal = getGraphTraversalSource().V(id);
}else{
graphTraversal = getGraphTraversalSource().V();
}
if(StringUtils.isNotEmpty(label)){
graphTraversal = graphTraversal.hasLabel(label);
}
if(propertys!=null&&propertys.size()>0){
for (Object o : propertys.entrySet()) {
Map.Entry entry = (Map.Entry) o;
String key = entry.getKey().toString().trim();
String value = entry.getValue().toString().trim();
if(StringUtils.isNotEmpty(key) &&
StringUtils.isNotEmpty(value))
graphTraversal = graphTraversal.has(key, value);
}
}
return graphTraversal;
}
@Override
public GraphTraversal timeLineGraphPath(String id, String label,
Map<String, Object> propertys,
String[] edgeLabels, String type,
String beginTime, String endTime) {
GraphTraversal graphTraversal = createGraphTraversalByIdLabel(id,label,propertys);
if(edgeLabels==null||edgeLabels.length==0)
return graphTraversal.valueMap(true);
else
return graphTraversal.outE(edgeLabels).and(__.has(type,P.gte(beginTime)),__.has(type,P.lte(endTime))).outV().path().order().by(type);
}
其中的”_.“是填充字符,只是为了可以使用方法,比如and( _.has(type,P.gte(beginTime)。。中如果没有__.的话,不能这写吧,也不支持呀and(.has()。。