查询以搜索首先显示特定用户的“朋友”和“朋友的朋友”的用户

时间:2015-09-06 23:49:14

标签: neo4j cypher social-networking

我是新工作的neo4j和Cypher。

目前我正在使用neo4j开发一个社交网站来获取数据。这将在顶部栏中有一个搜索选项,以便在社交网络上查找其他用户,但对于结果,我想先显示那些朋友,然后是朋友的朋友,然后是其他人。所有这些,分页搜索结果就像在facebook中搜索一样。

为实现这一目标,我正在寻找使用Cypher为此搜索选项创建最佳查询的方法。

我的USER节点有这样的结构:

(me:User { mid:"1234", name:"John Doe", email:"juan.arango1234@gmail.com" })

“mid”属性是自定义ID。

USER节点之间的友谊关系在两个方向都有标签“FRIENDOF”:

(a:User)-[:FRIENDOF]->(b:User) and (a:User)<-[:FRIENDOF]-(b:User)

我为此设计的最有效的查询是:

MATCH p = allShortestPaths((me:User)-[:FRIENDOF*]->(other:User))
WHERE me.mid = "1234"
AND other.name = "Any user name"
RETURN other, length(p) AS Length
ORDER BY length(p) ASC
SKIP 10
LIMIT 10

这个查询似乎运行良好,但我不能理解这个查询应该有更优化的方法。

按照Neo4j文档(http://neo4j.com/docs/stable/cypher-cookbook-friend-finding.html)的示例,我尝试通过将朋友,朋友的朋友和其他人的查询与UNION操作混合来创建此查询,但是使用UNION我无法将结果分页到实际问题1879(https://github.com/neo4j/neo4j/issues/1879)和相关2725,查询“其他”需要先前查询的结果(朋友和朋友的朋友)

在neo4j术语中使这个查询更便宜的任何更好的想法?

如何搜索不是朋友的朋友或朋友的朋友?

谢谢!

1 个答案:

答案 0 :(得分:2)

您有一个很好的查询起始块。您只需要认为 shortestPath 应该是可选的(因此用户没有连接),因此,考虑到这一点,您可以执行以下查询:

MATCH (me:User {mid:"1234"}), (other:User {name:"Any User name"})
OPTIONAL MATCH p=shortestPath((me)-[:FRIEND*1..2]-(other))
RETURN me.mid, other.mid, length(p) as distance
ORDER BY distance DESC

如果两个用户之间没有路径,则距离将为 null ,因此您可以在应用程序级别进行检查。

提示:shortestPath的默认深度限制为15。

参考演示图:http://console.neo4j.org/r/t2n1qc

修改

此查询基于演示控制台,用于检索共同的朋友数量:

MATCH (me:User { login:'randall.tremblay' })
MATCH (search:User { login:'witting.franz' })
OPTIONAL MATCH p=shortestPath((me)-[:FRIEND*]-(search))
WITH me, search, p, size((me)-[:FRIEND]-()-[:FRIEND]-(search)) AS common
RETURN me.login, search.login, length(p) AS distance, common