怎么实现点的关联查询

  • nebula 版本:v2-ga
  • 部署方式(分布式 / 单机 / Docker / DBaaS):单机
  • 是否为线上版本:N

查询点很简单,但怎么把它关联的点的数据也一起查出来。

举一个很常见的例子:查询文章详情

这是schema:

CREATE TAG user(
	name string
) 
CREATE TAG theme(
	name string
)
CREATE TAG post(
	text string
)
create edge author();  // post的作者
create edge themes(); // post所属的主题

现在要查询文章详情,包含text、作者、文章所属主题。

期待查询的类似结果:

{
	id: 24567434,
	text: "今天天气不错",
	author:{
		id: 1434652,
		name: "小明"
	},
	themes: [{
		id: 5434652,
		name: "日常生活"
	}],
}

这个查询怎么写 ?
@yee

相关联的点是通过edge连接起来的,这样的查询相当于给一个起始点然后沿着边向外拓展。
你例子中的查询可以写成: match(v:post)-[e:author | :themes]-(v2) return v2

match(v:post)-[e:author | :themes]-(v2) return v2

@Aiee 这样写数据是混杂在一起的,根本达不到预期效果。

1,[e:author | :themes]两条边都指向v2,合并在一起了,怎么区分?怎么分别获取?

2,如果都以v2来输出的话,那么同一条数据,它会多次输出,写了多少条边就输出多少次,出来的都是不完整的重复数据。明明只有一条数据,却输出n条。

match(v:post)-[e:author | :themes]-(v2) return v2.name,  v2.desc

3,不同边拥有相同的属性名,属性冲突
就比如上面,author和themes都拥有name属性,但是他们都聚合在v2,这样就有问题。

我觉得如果支持下面的写法,就没有上面的问题:

每条边都可以指定一个接收点,而不是都汇聚于一个点上。

match(v:post)-[a:author | t:themes]-(va, vt) return va.name,  vt.name

但是现在不支持,以上的问题该怎么处理 ?

一个区分的终点是从哪条边来的方法:
match(v:post)-[e:author | :themes]-(v2) return type(e), v2.name
获取特定边上的结果:
match(v:post)-[e:author | :themes]-(v2) with type(e) as type, v2.name as name where type=="e:author" return type, name

match(v:post)-[e:author | :themes]-(v2) with type(e) as type, v2.name as name where type==“e:author” return type, name

这样不行的,同样会重复输出,而且只能过滤其中一个,那如果很多个呢

首先,类似 match(v:post)-[e:author | :themes]-(v2) return type(e) 这样的语法 cypher 是不支持的,我认为这对 pattern 实现是有害的,具体 pattern 使用可以参考:cypher-pattern-relationship

你的需求可以用多 pattern 或者 pattern type 过滤解决,多 pattern 目前 nebula 还不支持。

那现在这个需求怎么实现 ? 上面的都是不行的。
关联查询,这是很常见,很基本的需求,你们做研发的时候都不会去考虑的吗?现在做一些简单的东西实现起来都很费劲,甚至无法实现,哎。。。说句扎心点的话,感觉你们做研发是面向实验室,不是面向市场 :sleepy:

MATCH (v:post)-[]->(a:author), (v)-[]->(t:themes) 
RETURN v.text, a.name, collect(DISTINCT t.name)

这条语句比较契合你的需求,现在多 pattern 还不支持。
单 pattern 确实数据会混杂在一起。

MATCH (v:post)-->(a:author), (v)-->(t:themes)
RETURN v.text, a.name, collect(DISTINCT t.name)

语法报错:SyntaxError: syntax error near `, (v)-

箭头不是应该指向顶点吗,为啥指向边

多 pattern 还不支持。

包含属性的实体概念最好是做成点。

那现在这个需求实现不了了?nGQL能实现吗?
多 pattern是下个版本支持吧?大概什么时候发布 ?
哎,就这么个简单的需求搞了2天了

MATCH (a:author)<-[]-(v:post)-[]->(t:themes)
RETURN v.text, a.name, collect(distinct t.name)

目前,这条语句是可以支持的

还是会报错:SemanticError: `author’: Unknown tag

如果支持下面这样的nGQL写法就好了,点和边各自去查,最后合并在一起:

$owner = go from "01" over owner yield owner._dst as id, $$.owner.name;
$theme = go from "01" over themes yield themes._dst as id, $$.themes.name;
fetch prop on post "01" yield post.text as text, $owner as owner, $theme as theme

但是fetch yield后面不支持变量,会报错。go yield后面支持变量,fetch yield后面不支持,搞不懂为啥要这样设计

schema 需要改一下:

CREATE TAG post(id int, text string) 
CREATE TAG author(id int, name string)
CREATE TAG themes(id int, name string)
create edge writes();
create edge relates();
// insert tags and edges...
MATCH (a:author)<-[]-(v:post)-[]->(t:themes)
RETURN v.text, a.name, collect(distinct t.name)

我试试

nGql 的语法确实有时候会比较不方便,试试这个:

LOOKUP ON post YIELD post.text AS text
| YIELD $-.VertexID AS vids, $-.text AS text
| GO FROM $-.vids OVER writes,relates REVERSELY YIELD $-.vids AS vids, $-.text AS text, $$.author.name as n1,$$.themes.name as n2 
| YIELD $-.text, $-.n1, collect($-.n2)

CREATE TAG post(id int, text string)
CREATE TAG author(id int, name string)
CREATE TAG themes(id int, name string)
create edge writes();
create edge relates();
// insert tags and edges…
MATCH (a:author)<--(v:post)-->(t:themes)
RETURN v.text, a.name, collect(distinct t.name)

这样可行,但只能局限于1-2条边的情况 ,2条以上的边怎么办 ?通常一个点可能有4-6条边

1 个赞

两个以上的边只能等支持多 pattern 了。也可以仿照上面 nGql 的写法,over 多种边类型。