neo4j-返回节点的单个实例-按属性查询?

时间:2019-05-25 17:24:07

标签: neo4j cypher

我正在建立一个具有专门受众的社交网络。

用户通过三种主要的关系类型相互关联。

[:FRIENDS]->(:USER), 
[:WORKS_AT]->(:COMPANY), 
[:WORKED_AT]->(:COMPANY), 
[:FOLLOWS]. 

在进行搜索时(一个用户想找到另一个用户),我为每种关系都赋予了“优先级”(可以这么说)。

例如,如果某个用户想要找到另一个名为“ Bart Simpson”的用户-首先,我们将检查同事之间的关系([:WORKS_AT],[:WORKED_AT])。我已将这些关系的优先级设置为1。这样,与我一起工作的“巴特·辛普森”将出现在搜索结果中,而“巴特·辛普森”(居住在斯普林菲尔德的数百英里之外)之前。

第二个优先级是[:FRIENDS]->(:USER)。我的朋友中有没有一个叫“巴特·辛普森”的朋友?优先级2。

最后一个优先事项是全局搜索。我没有名为“ Bart Simpson”的同事,我的朋友没有名为“ Bart Simpson”的朋友-但是我在会议上遇到了Bart,我想与他成为“朋友”。因此,我添加了“全局”搜索。查找名为“ Bart Simpson”的所有用户。

到目前为止,这是我的Cypher:

optional match (u:USER {id:'1'})-[:WORKS_AT|:WORKED_AT]-(w:COMPANY)-[r]-(f:USER)
with collect(f{.*, priority:1,relationship:r.title,type:type(r)}) as user
optional match (u:USER {id: '1'})-[:FRIENDS]-(:USER)-[r:FRIENDS]-(f:USER)
with user + collect(f{.*, priority:2,relationship:r.title,type:type(r)}) as user
optional match (f:USER)
where f.id <> '1'
with user + collect(f{.*, priority:3,relationship:'',type:''}) as user
unwind user as users 
with users as user
where toLower(user.last_name) STARTS WITH toLower('Sc') OR toLower(user.first_name) STARTS WITH toLower('Sc')
return distinct user

这太棒了-但是,用户可以在同一家公司工作, 成为朋友,以及出现在全局搜索中。因此-我们具有相同用户三(或更多)份“副本”的潜力-具有不同的关系属性。关系属性很重要,因为在应用程序中,它们为搜索提供了重要的上下文。 “巴特·辛普森-在XYZ公司工作。”

所以我真正想要的是能够返回具有最高优先级的用户记录-并根据“ ID”字段执行此操作。如果这不起作用,我会看到一种情况,我们尝试更新节点的属性。因此,当查询命中优先级2搜索时,如果集合中已经有一个用户具有相同的“ ID”,则只需将P2关系类型附加到记录中即可。对我来说都很好。

我愿意接受建议和倾听!

1 个答案:

答案 0 :(得分:0)

所以,我已经取得了一些进步!

MATCH 
    (subject:USER {id:'1'})
MATCH
    (subject)-[:WORKS_AT|:WORKED_AT]-(w:COMPANY)-[r]-(f1:USER)
WHERE 
    toLower(f1.last_name) STARTS WITH toLower('Sc') or 
    toLower(f1.first_name) STARTS WITH toLower('Sc')
WITH 
    COLLECT(f1.id) AS userIds, 
    COLLECT(f1{.*,priority:1,rType:type(r), title:r.title, detail:w.name}) AS users
OPTIONAL MATCH
    (subject)-[:FRIEND]-(fw:USER)-[r:FRIEND]-(f2:USER)
WHERE 
    NOT(f2.id in userIds) AND 
    (
        toLower(f2.last_name) STARTS WITH toLower('Sc') or 
        toLower(f2.first_name) STARTS WITH toLower('Sc')
    )
WITH 
    users + COLLECT(f2{.*,priority:2,rType:"FRIEND", title:"Friends with " + fw.first_name + " " + fw.last_name, detail:''}) AS users, 
    userIds + collect(f2.id) AS userIds
OPTIONAL MATCH
    (f3:USER)
WHERE 
    NOT(f3.id in userIds) AND 
    (
        toLower(f3.last_name) starts with toLower('Sc') OR 
        toLower(f3.first_name) starts with toLower('Sc')
    )
WITH 
    users + COLLECT(f3{.*,priority:3,rType:"GLOBAL", title:"", detail:''}) AS users
RETURN  
    users

查询有所发展。本质上,在第一阶段,我们收集返回的项目的用户ID。在随后的每个阶段,将返回的结果与ID的运行列表进行比较。如果结果的ID已在ID列表中,则会将其过滤掉,从而确保该ID在该集合中是唯一的。

这正在工作-现在,我将继续使用它。这是最有效的查询,还是有更好的方法来处理这种情况?