图数据库入门教程(六)复杂关系查询
涉及的语法,关于语法更多的使用方式参考官方文档
- aggregate
- where
- without
- group
- groupCount
- order
- cap
- unfold
- local
可能认识的人
查询可能认识的人
g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x'))
这个语句复杂一些,我们一步一步解析
- g.V().has('person','name','张三'):查询出张三
- .aggregate('x'):将张三存放到一个叫x的list中,aggregate就是将一个list存放到一个容器中,现在的容器是x
- .both():查询出张三的朋友
- .aggregate('x'):将张三的朋友也放到x list中
- .both():查询张三的朋友的朋友
- .where(without('x')),从结果中过滤掉x中的数据,也就是过滤掉张三本人和张三的朋友
1. aggregate()
将前面的查询结果放入一个list中,g.V().aggregate('x'),将g.V()查询出的所有结果放入一个叫'x'的list中,如果一个语句中多个aggregate的字符是同一个,比如上面的aggregate('x'),那么它们之间不是覆盖关系,而是叠加关系。例如
g.V().has("person","name","张三").out().aggregate('x').out().aggregate('x').cap("x")
cap的作用是将x输出。
2. where()
where条件,用于包装一些过滤条件
3. without()
对前面的结果进行排除,排除在指定list中,如果需要是在指定的list中,可以用within()
上面的查询前几部好理解,第六步张三的朋友的朋友中怎么会有张三自己和张三的朋友呢?如果站在张三的朋友的顶点上,再次both查询张三朋友的朋友时按照途中这么查是没问题的
但现实是怎样的呢?
所以我们在查询过程中,将张三,张三的朋友都放到一个list中,查询出结果后,过滤掉即可。
可能认识的人排序
上面的可能认识的人,也就是朋友的朋友,怎么排序呢?当然是你的越多朋友认识一个人,那这个人就排在前面,怎么做呢?
再插入一条关系如下
g.V().has('person','name','孙八').addE('know').to(__.V().has('person','name','朱七')).property('knowTime',2015)
修改gremlin语句如下
g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x')).group().by('name').by(count()).order(local).by(values,desc)
查出结果
[
{
"朱七": 2,
"赵六": 1
}
]
这么"智能"的算法居然被我们轻而易举的实现了!
4. group()
对前面的查询结果进行分组,分组的依据是什么呢?通过by指定,如上我们根据name进行分组,再通过一个by(count()),计算每一项的数量,此时的结果是这样的
[
{
"朱七": 2,
"赵六": 1
}
]
如果不加by(count())是怎样的呢?
[
{
"赵六": [
{
"id": 12312,
"label": "person",
"properties": [
...
]
}
],
"朱七": [
{
"id": 8360,
"label": "person",
"properties": [
...
]
},
{
"id": 8360,
"label": "person",
"properties": [
...
]
}
]
}
]
不同于both(),in(),out()操作,group之后数据结构不再是元素列表,而是一个map,如下图
我们可以通过select()的方式将Map中的keys或values单独输出
g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x')).group().by('name').by(count()).select(keys)
[
[
"赵六",
"朱七"
]
]
g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x')).group().by('name').by(count()).select(values)
[
[
1,
2
]
]
5. groupCount().by()
groupCount().by('name')等于,group().by('name').by(count())
6. order()
对所有人按照年龄属性倒序排列
g.V().hasLabel("person").order().by('age', desc)
输出
g.V().hasLabel("person")后会查询到所有person顶点,然后order by顶点的age属性值倒序排列,得到了我们想要的结果。
那对group后的结果如何排序呢?通过上面对group的讲解,我们知道group后的结果是一个map,我们想根据map的values倒序排列
具体的写法是
order(local).by(values, desc),一定要加local,否则不生效。
g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x')).group().by('name').by(count()).order(local).by(values,desc)
除此之外,还有一种写法就是用unfold先把结果展开,再排序
unfold().order().by(values, desc)
[
{
"朱七": 2
},
{
"赵六": 1
}
]
可以看到,排序效果是预期的,但是结构不同,unfold把map的每个元素都展开为一个单独的对象。