我想从我的数据集中获取国家/地区列表。假设组织我正在为#34;操作"在各个国家。但是,操作的定义可以通过几种方式构建。
首先,如果有一个人为在该国家的公司工作。
第二,如果该国家/地区支持任何获奖企业(如果该奖项中的任务附属于该国家/地区,该奖项已知在该国家/地区)
第三,如果该组织获得特别许可在那里开展业务。例如,该公司可能已获得许可,但实际上并未在那里进行任何工作。
所以,我希望从另一端获得一些json,我可以用它来支持与svg国家地图的互动。这意味着我要么需要满足这些标准的国家的json列表,以及有关每个国家/地区遇到的标准(e.g.: {Country:"The United State", Code:"USA", hasPeople:true, hasActiveAward: false, isLicensed:true})
的一些信息,或者我需要三个单独的列表(每个标准一个)和一个子集其中的国家。
我尝试了各种各样的事情,包括下面的这一部分,这一部分失败最为惊人,同时也是最简单的阅读理解。
// get all types of country
match (c1)<-[:SITS_IN|GEO_IN*]-(p:Person)
match (c2)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(a:Award {awardStatus:"ACTIVE"})
match (c3)<-[:LICENSED_IN]-(d:Department)
return {
peopleCountries:[{country:c1.name, code:c1.code, people:count(p)}],
awardCountries:[{country:c2.name, code:c2.code, awards:count(a)}],
licensedCountries:[{country:c3.name, code:c3.code, department:d.name}]
}
这是我试过的另一个实际上工作正常,但仍然需要大约14秒才能运行:
match (c:Country)
where exists((c)<-[:SITS_IN|GEO_IN*]-(:Person)) or
exists((c)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(:Award {awardStatus:"ACTIVE"}))
or exists((c)<-[:LICENSED_IN]-(:Department))
with c
optional match (c)<-[:SITS_IN|GEO_IN*]-(p:Person)
optional match (c)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(a:Award {awardStatus:"ACTIVE"})
optional match (c)<-[:LICENSED_IN]-(d:Department)
with c, count(p) as people, count(a) as awards, d.name as department
return {
country:c.name,
people:people,
awards:awards,
department:department
}
任何帮助非常感谢。我认为我应该将这些请求分成三个完全独立的请求,或者使用路径变量,但我还是刚刚开始使用Cypher,所以我愿意学习更好的方法来考虑这个问题。 。
谢谢!
答案 0 :(得分:2)
要注意的一件事是连续多个匹配或可选匹配,您的意图是稍后汇总结果。请记住,Neo4j将结果构建为行,并处理这些行上的操作(匹配和可选匹配),即使它是多余的。
例如,参加前两个可选比赛:
with c
optional match (c)<-[:SITS_IN|GEO_IN*]-(p:Person)
optional match (c)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(a:Award {awardStatus:"ACTIVE"})
让我们说一个国家,比如说法国,由于第一场可选比赛,有50人。仅在法国,我们现在有50排:法国与每个匹配的人配对。现在我们运行第二个可选匹配,即使你打算每个国家只执行一次,它每行执行一次,所以它对法国的每一行在法国执行50次与第一场比赛的人。
等等。如果在法国找到3个奖项,那么现在法国有150排,法国的每个组合排成一排,匹配的人之一,以及匹配的奖项之一。现在,最后一个可选匹配必须在这150行上运行。当您正在处理多个国家时,这对于一个国家来说只是理论上的。
为避免这一切,最好立即处理每个可选匹配的聚合,在它们之间使用WITH,因此在每个WITH之后,每个国家/地区的行数保持不变。这适合您的可选匹配,因为它们都来自一个国家/地区,您的目的是让它们每个国家/地区运行一次,而不是多次运行。改进后的查询可能如下所示:
match (c:Country)
where exists((c)<-[:LICENSED_IN]-(:Department))
or exists((c)<-[:SITS_IN|GEO_IN*]-(:Person))
or exists((c)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(:Award {awardStatus:"ACTIVE"}))
with c
optional match (c)<-[:SITS_IN|GEO_IN*]-(p:Person)
with c, count(distinct p) as people
optional match (c)<-[:TASK_IN_COUNTRY]-(:Task)-[:PART_OF*2]->(a:Award {awardStatus:"ACTIVE"})
with c, people, count(distinct a) as awards
optional match (c)<-[:LICENSED_IN]-(d:Department)
with c, people, awards, collect(d.name) as departments
return {
country:c.name,
people:people,
awards:awards,
departments:departments
}
我重新排序了你的第一个匹配谓词,这样就可以更容易,更快速地进行比较,这样可以避免不必要地执行更复杂的谓词。
我还收集了在该国获得许可的部门(我假设多个部门可以获得许可,而不仅仅是一个部门)。
每个国家/地区的输出应该是一行。