我目前正在一个社交媒体网站上工作,该网站在用户时间轴方面完全相同,例如用户可以关注,创建,共享帖子,屏蔽,取消屏蔽等。为此,我们创建了两种类型的标签为“用户”和“发布”,并具有以下关系,例如关注,阻止,私有等。 目前,我们大约有41000个节点和650000个关系。
硬件配置: 8 GB内存 2芯 50 GB硬盘
1个主人和2个奴隶
并使用以下查询获取用户的时间轴
function writeToLog($data, $title = '') {
$log = "\n------------------------\n";
$log .= date("Y.m.d G:i:s") . "\n";
$log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n";
$log .= print_r($data, 1);
$log .= "\n------------------------\n";
file_put_contents(getcwd() . '/hook.log', $log, FILE_APPEND);
return true;
}
此查询耗时超过10秒。太高了
以下是上述查询的个人资料
有人可以建议我在哪里做错了吗?
答案 0 :(得分:2)
如果您想获取用户的时间轴,我认为您应该从特定用户开始,然后通过您感兴趣的关系连接到其他节点。当前查询没有利用模式匹配或图数据库的连接性质。
当前编写的查询的第一个match语句先找到一个特定用户,然后找到所有具有is_deleted:'0'属性的Post节点,然后再找到连接到任何Post节点的所有User节点。通过这种方式进行搜索,与数据库中的节点数(41,000)相比,在第一个中间Expand(All)中数据库命中数(54,984)更多。
最优化此查询的地方是将搜索集中在单个用户上,然后使用以下关系从那里扩展:
MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r]-(p:Post{is_deleted:'0'})
这将匹配用户以及通过关系连接到该用户的所有合格帖子。请注意,如果用户没有连接到任何合格的帖子,则即使该用户确实存在于数据库中也不会有任何匹配项。
如果只想包括某些关系类型,则可以在第一个MATCH语句中指定为这种关系类型:
MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r:CREATED|FOLLOWS|KEYWORD]-(p:Post{is_deleted:'0'})
或者您可以像这样将其放在WHERE子句中:
MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r]-(p:Post{is_deleted:'0'})
WHERE type(r) in ['CREATED', 'FOLLOWS' , 'KEYWORD']
我没有遵循所有的条件语句(我认为将其转换为模式匹配后,您也许可以删除其中的一些条件语句),但是一旦有了初始模式,就可以添加所需的任何条件语句。示例:
WHERE (p.post_type = '1' OR p.post_type = '4')
AND (r.own_status = '1' OR r.follow_status = '1')
AND NOT r.is_blocked = true
有关模式匹配的更多信息,请查看Neo4j Cypher Manual的2.9节。