match多语句查询

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

schema:

create tag post( title string NOT NULL );
create edge likes(); 

目前的需求: 根据关键词搜索 文章列表,包含判断 登录用户 是否已点赞该文章。

因此需要做两步工作,1,搜索文章列表,需要模糊查询 。2,传入登录用户id,检索每篇文章的点赞列表中,是否包含登录用户。

这需要2个查询语句。

nGQL我不知道怎么写,lookup不支持CONTAINS做模糊查询,第一步就没法做。go where支持CONTAINS,但那是查边的。

es全文搜索又重又耗资源,不想弄它,我只需简单的模糊查询就可以了。

似乎只能用match了,如下:

MATCH p=(v:post) WHERE v.title CONTAINS '人工智能' return v.title

这只完成了第一步,第二步判断用户是否点赞就不知道怎么写了,我测试了下,好像不支持在match中嵌套另一个match语句,所以根本不知道怎么写

难点在于第二步,求教怎么写才能实现这个功能

关于2,假设已经有了登录用户id列表,在客户端把它攒成 [“player104”, “player102”] ,做类似如下MATCH,不知道能够不能满足你的需求呢?

MATCH (t:team { name: 'Warriors' })-[e:serve]-(p) \
WHERE id(p) IN ["player104", "player102"] RETURN p;
MATCH p= (u:User)-[l:likes]->(p:post) WHERE id(u) == "$UserAccount$" AND p.title CONTAINS '人工智能' RETURN exists(l), l IS NOT NULL

p.title CONTAINS 这个操作的性能可能会很慢

1 个赞

MATCH (t:team { name: ‘Warriors’ })-[e:serve]-(p)
WHERE id(p) IN [“player104”, “player102”] RETURN p;

@wey 我是要做搜索,根据关键词搜索文章,另外附带用户点赞状态。你这个查询明显不符合。

p.title CONTAINS 这个操作的性能可能会很慢

@min.wu 这个查询也不对,我要查的是根据关键词全局搜索出来的文章列表,不是某用户点赞的文章列表。只是搜索出来的文章附带用户点赞状态而已。你上面语句只会查出这个用户点赞的文章列表。

p.title CONTAINS 这是普通的模糊查询,为什么会很慢? 有多慢 ?

1 个赞

中文是这样的吧?

中文是这样的吧?

啥意思? 总之就是做全局搜索文章的功能, 附带用户点赞状态,这个具体怎么写

1,搜索文章列表,需要模糊查询 。
2,传入登录用户id,检索每篇文章的点赞列表中,是否包含登录用户。

是这样的意思么?

query_1:
  input: "key_word0"
  output: list_of_posts_contains_key_word0
query_2:
  input:
    - "user_id0"
    - posts_with_some_conditions
  output:
    - bool(if user:"user_id0" liked posts_with_some_conditions[0])
    - bool(if user:"user_id0" liked posts_with_some_conditions[1])
    - bool(if user:"user_id0" liked posts_with_some_conditions[2])

如果是的话,min 的query里, posts_with_some_conditionsquery_1的要求,这里可能我们误解你了。
实际上你的需求里:检索每篇文章,只的是所有posts?还是?

@wey
这是个很常见的需求。以知乎为例,你登录知乎打开首页,在搜索框输入关键词 “nebula” 搜索所有关于nebula的文章,然后会出来一堆关于nebula的文章,且附带用户状态的(我是否已评论/点赞该文章)。

请看下图:

图里的第二步就是我上面说的。

第一步很简单,就是简单的搜索。关键是第二步,我需要知道我是否已点赞我搜索出来的文章。这个就要去查文章的likes列表中是否有我,以此来判断我是否已点赞该文章。

这个要怎么实现

明白了:

这个就要去查文章的likes列表中是否有我,以此来判断我是否已点赞该文章。

这里假设你已经获取了文章列表 ["foo", "bar"] 然后可以一次query得出被喜欢的子集。
下边是我改造了的 @min.wu 的 query:

这里 $UserAccount$ 和 post列表是这个query的 input,p是输出,你可以直接根据输出得到给定(模糊搜索出的)post_list里用户 liked的 post的子列表。

这里假设你已经获取了文章列表 [“foo”, “bar”]

@wey 没有假设,match根本不支持多语句。搜索文章和搜索点赞是两条match语句,根本没法写在一起

所以你是期待着这个query里只带 UserAccount ,不打算在client端从query1得到文章列表来构造query2。

如此的话就更接近 @min.wu 老师开始给的query了。

MATCH p= (u:User)-[l:likes]->(p:post) \
    WHERE id(u) == "$UserAccount$" \
    AND p.title CONTAINS 'foo' RETURN p;

假设这里是zhihu的客户端逻辑,客户端先做 query_1得到所有文章列表(渲染文章列表),再做 query_2获取已经点赞列表(渲染赞的按钮)

对于query_2 的构造如果直接把query 1的结果带进去(传post list, 用 IN ,少一次 CONTAINS)会更好一些。

而您的意思是希望实现上边的请求从两次变成一次?

1 个赞

假设这里是zhihu的客户端逻辑,客户端先做 query_1得到所有文章列表(渲染文章列表),再做 query_2获取已经点赞列表(渲染赞的按钮)

你意思是先发请求1:查文章列表。 拿到文章 [ids] 后,再发请求2:批量查询文章的用户点赞状态 ?

两次请求,两次查询,是这样吗 ?

我的想法是,在一次查询里面完成上面两步工作

你意思是先发请求1:查文章列表。 拿到文章 [ids] 后,再发请求2:批量查询文章的用户点赞状态 ?

两次请求,两次查询,是这样吗 ?

我的想法是,在一次查询里面完成上面两步工作

是的,您这个需求需要一个query里有超过一个match才能做到,非常抱歉我们现在还不支持多个MATCH在一个QUERY里。

哎。。。用下来感觉nebula好鸡肋,宣传倒是很猛烈,但是连很多基础功能都没实现。。。 :expressionless:

非常非常抱歉给了您这么不好的感受,nebula一步一步走下来,很多都是社区用户们一点点教我们如何变的更好的,我们特别珍惜 panda 您的参与,帮助和提出的点。
作为先驱和社区热心的一员感谢 panda 一直以来的贡献(有去看您之前的帖子:+1:t2:),让您失望我真的非常难过。
一定会把您的声音让社区听到的,一点点做好关于openCypher的兼容工作。

不知道这个限制影响对您有多大,能不能先从数据库客户端代码上做一些工作先缓解呢(真的非常抱歉)?

影响太大了,目前的nebula只能满足一些基础的功能,复杂一点的根本做不了

多 MATCH 组合的语法在接下来的版本(大概年中)就会支持,请再稍微等待一些时间。目前可以通过 pipe 接 GO 的方式解决,类似如下:

MATCH (v:post)
WHERE v.title CONTAINS '人工智能' 
RETURN v.ttile as title, id(v) as vid
|
GO FROM $-.vid OVER like REVERSELY YIELD $-.title as title, (like._dst == "current_user_vid") AS liked
4 个赞

Yee 老师太赞了,原来 这种混杂的 pipe也可以,还能中间return

Panda 您有需求对nebula的改进也欢迎去相应的repo提issue哈。

谢谢!

目前可以通过 pipe 接 GO 的方式解决

@yee 谢了哈,这样的确可以,也没想到过,因为文档里说管道符只能用于 nGQL, match和nGQL不能混着用,原来是可以的。。。。

多 MATCH 组合的语法在接下来的版本(大概年中)就会支持

其实我更期待 lookup 能支持模糊查询,这样就能用nGQL来实现。match性能比较差,迫不得已的话,不是很愿意用。

1 个赞

@wey @yee
还是有问题,重复数据:

...
RETURN v.title as title, id(v) as vid
|
GO FROM $-.vid OVER like REVERSELY YIELD (like._dst == "current_user_vid") AS liked

这里最后一个yield循环输出go查询的like列表而不是match查询的post列表,所以like有多少个就输出多少次,但对应的post-vid只有一个,于是导致很多重复数据,还有就是同一个post,liked有时是true,有时是false。。。