我目前正在一个社会媒体网站,这完全是在用户的时间轴方面相同的工作,像用户可以遵循,创建,分享的职位,块,解除封锁,等.因此,我们创建了两种类型的标签“User”和“Post”,并有几个关系,如follow,block,private等。目前,我们有大约41000个节点和650000个关系。
硬件配置:8 GB RAM 2核心50 GB硬盘
1个Master和2个Slave
并使用以下查询获取用户的时间轴
MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'}),(p:Post{is_deleted:'0'}),(po:User{user_id:p.owner_id})
WHERE (p.post_type = '1' OR p.post_type = '4') WITH n,p,po
WHERE po.is_active='1' AND (n)-[:CREATED{own_status:'1'}]->(p) OR
(n)-[:FOLLOWS{follow_status:'1'}]->(:User{is_active:'1'})-[:CREATED{own_status:'1'}]->(p)
OR (n)-[:FOLLOWS{follow_status:'1'}]->(:Keyword{is_deleted:'0'})-[:KEYWORD]->(p)
WITH n,p,po
OPTIONAL MATCH (n)-[fr:FOLLOWS]->(po)
WHERE fr.follow_status='1' WITH p,n,po,fr
WHERE NOT ((n)-[:FOLLOWS{is_blocked:true}]->(po) OR (n)-[:FOLLOWS{is_mute:true}]->(po)) WITH p,n,po,fr
WHERE NOT (n)<-[:FOLLOWS{is_blocked:true}]-(po) WITH p,n,po,fr
WHERE (fr is not null and toInteger(po.is_private) <= 1 AND po.user_id <> n.user_id)
OR (toInteger(po.is_private) <= 1 AND po.user_id = n.user_id)
OR (toInteger(po.is_private) = 0 AND po.user_id <> n.user_id) WITH p,n,po
RETURN p,po,SIZE(()-[:LIKED]->(p)) as likecount,
SIZE((n)-[:LIKED]->(p)) as likestatus,count(*) as postcount
ORDER BY p.created_at DESC
SKIP 0 LIMIT 10
此查询耗时超过10秒。太高
下面是上述查询的配置文件
下面是索引列表
有谁能告诉我哪里做错了吗?
1条答案
按热度按时间c9x0cxw01#
如果你试图获取用户的时间轴,我认为你应该从特定的用户开始,然后通过你感兴趣的关系连接到其他节点。当前的查询没有利用模式匹配或图数据库的连接特性。
当前编写的查询的第一个match语句查找特定的用户,然后是具有属性is_deleted:'0'的所有Post节点,然后是连接到任何Post节点的所有User节点。这样搜索会在第一个中间的Expand(All)中得到比数据库中的节点数(41,000)更多的数据库命中数(54,984)。
在优化这个查询时,你应该得到最大的提升,那就是将搜索集中在单个用户上,然后使用关系从那里扩展:
这将匹配用户和通过关系连接到该用户的所有合格职位。请注意,如果用户没有连接到任何符合条件的职位,即使该用户确实存在于数据库中,也不会有任何匹配。
如果你只想包含某些关系类型,你可以在第一个MATCH语句中这样指定:
或者你可以像这样把它放在WHERE子句中:
我没有遵循你所有的条件语句(我认为一旦你将其转换为模式匹配,你可能可以删除其中一些),但是一旦你有了你的初始模式,你可以添加任何你需要的条件语句。范例:
有关模式匹配的更多信息,请查看Neo4j Cypher Manual的第2.9节。