Loading

图数据库入门教程(六)复杂关系查询

涉及的语法,关于语法更多的使用方式参考官方文档

  • aggregate
  • where
  • without
  • group
  • groupCount
  • order
  • cap
  • unfold
  • local

可能认识的人

img

查询可能认识的人

g.V().has('person','name','张三').aggregate('x').both().aggregate('x').both().where(without('x'))

这个语句复杂一些,我们一步一步解析

  1. g.V().has('person','name','张三'):查询出张三
  2. .aggregate('x'):将张三存放到一个叫x的list中,aggregate就是将一个list存放到一个容器中,现在的容器是x
  3. .both():查询出张三的朋友
  4. .aggregate('x'):将张三的朋友也放到x list中
  5. .both():查询张三的朋友的朋友
  6. .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")

img

cap的作用是将x输出。

2. where()

where条件,用于包装一些过滤条件

3. without()

对前面的结果进行排除,排除在指定list中,如果需要是在指定的list中,可以用within()

上面的查询前几部好理解,第六步张三的朋友的朋友中怎么会有张三自己和张三的朋友呢?如果站在张三的朋友的顶点上,再次both查询张三朋友的朋友时按照途中这么查是没问题的

img

但现实是怎样的呢?

img

所以我们在查询过程中,将张三,张三的朋友都放到一个list中,查询出结果后,过滤掉即可。

可能认识的人排序

上面的可能认识的人,也就是朋友的朋友,怎么排序呢?当然是你的越多朋友认识一个人,那这个人就排在前面,怎么做呢?

再插入一条关系如下

g.V().has('person','name','孙八').addE('know').to(__.V().has('person','name','朱七')).property('knowTime',2015)

img

修改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,如下图

img

我们可以通过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)

输出

img

g.V().hasLabel("person")后会查询到所有person顶点,然后order by顶点的age属性值倒序排列,得到了我们想要的结果。

那对group后的结果如何排序呢?通过上面对group的讲解,我们知道group后的结果是一个map,我们想根据map的values倒序排列

img

具体的写法是

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的每个元素都展开为一个单独的对象。

posted @ 2022-08-29 10:33  树先生1024  阅读(418)  评论(0编辑  收藏  举报