Neo4j Cypher查询结构和性能优化 [英] Neo4j Cypher query structure and performance optimization

查看:83
本文介绍了Neo4j Cypher查询结构和性能优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个Cypher查询动态生成器.对于复杂的情况,此构建器会产生很大的查询,例如:

I have created a Cypher query dynamic builder. For a complex cases this builder produces a quite big queries, for example:

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
WHERE id(parentD) = {decisionId} 
MATCH (childD)<-[:SET_FOR]-(filterValue415431:Value)-[:SET_ON]->(filterCharacteristic415431:Characteristic) 
WHERE id(filterCharacteristic415431) = 415431 
WITH filterValue415431, childD, ru, u 
WHERE  ({filterValue4154311} IN filterValue415431.value ) 
 OR ({filterValue4154312} IN filterValue415431.value ) 
 OR ({filterValue4154313} IN filterValue415431.value ) 
 OR ({filterValue4154314} IN filterValue415431.value ) 
 OR ({filterValue4154315} IN filterValue415431.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue415441:Value)-[:SET_ON]->(filterCharacteristic415441:Characteristic) 
WHERE id(filterCharacteristic415441) = 415441 
WITH filterValue415441, childD, ru, u 
WHERE  ({filterValue4154416} IN filterValue415441.value ) 
 OR ({filterValue4154417} IN filterValue415441.value ) 
 OR ({filterValue4154418} IN filterValue415441.value ) 
 OR ({filterValue4154419} IN filterValue415441.value ) 
 OR ({filterValue41544110} IN filterValue415441.value ) 
 OR ({filterValue41544111} IN filterValue415441.value ) 
 OR ({filterValue41544112} IN filterValue415441.value ) 
 OR ({filterValue41544113} IN filterValue415441.value ) 
 OR ({filterValue41544114} IN filterValue415441.value ) 
 OR ({filterValue41544115} IN filterValue415441.value ) 
 OR ({filterValue41544116} IN filterValue415441.value ) 
 OR ({filterValue41544117} IN filterValue415441.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue416273:Value)-[:SET_ON]->(filterCharacteristic416273:Characteristic) 
WHERE id(filterCharacteristic416273) = 416273 
WITH filterValue416273, childD, ru, u 
WHERE  (filterValue416273.value >= {filterValue41627318}) 
 AND (filterValue416273.value <= {filterValue41627319})  
MATCH (childD)<-[:SET_FOR]-(filterValue417410:Value)-[:SET_ON]->(filterCharacteristic417410:Characteristic) 
WHERE id(filterCharacteristic417410) = 417410 
WITH filterValue417410, childD, ru, u 
MATCH (childD)<-[:SET_FOR]-(filterValue416423:Value)-[:SET_ON]->(filterCharacteristic416423:Characteristic) 
WHERE id(filterCharacteristic416423) = 416423 
WITH filterValue416423, childD, ru, u 
WHERE  ({filterValue41642320} IN filterValue416423.value ) 
 OR ({filterValue41642321} IN filterValue416423.value ) 
 OR ({filterValue41642322} IN filterValue416423.value ) 
 OR ({filterValue41642323} IN filterValue416423.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue415673:Value)-[:SET_ON]->(filterCharacteristic415673:Characteristic) 
WHERE id(filterCharacteristic415673) = 415673 
WITH filterValue415673, childD, ru, u 
WHERE  ({filterValue41567324} IN filterValue415673.value ) 
 OR ({filterValue41567325} IN filterValue415673.value ) 
 OR ({filterValue41567326} IN filterValue415673.value ) 
 OR ({filterValue41567327} IN filterValue415673.value ) 
 OR ({filterValue41567328} IN filterValue415673.value ) 
 OR ({filterValue41567329} IN filterValue415673.value ) 
 OR ({filterValue41567330} IN filterValue415673.value ) 
 OR ({filterValue41567331} IN filterValue415673.value ) 
 OR ({filterValue41567332} IN filterValue415673.value ) 
 OR ({filterValue41567333} IN filterValue415673.value ) 
 OR ({filterValue41567334} IN filterValue415673.value ) 
 OR ({filterValue41567335} IN filterValue415673.value ) 
 OR ({filterValue41567336} IN filterValue415673.value ) 
 OR ({filterValue41567337} IN filterValue415673.value ) 
 OR ({filterValue41567338} IN filterValue415673.value ) 
 OR ({filterValue41567339} IN filterValue415673.value ) 
OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN {criteriaIds} 
WITH childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
WITH ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes  
ORDER BY  weight DESC 
SKIP 0 LIMIT 10 
RETURN ru, u, childD AS decision, weight, totalVotes, 
 [ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | 
  {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
 [ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) | 
  {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
 [ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) | 
  {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics

现在我对表演并不满意.例如,调用此查询大约需要500毫秒

Right now I'm not very happy with a performance. For example call on this query takes ~500ms

能否请您看看是否有机会改进此查询?

Could you please take a look and tell if there is a chance to improve this query ?

已更新

这是几乎相同的查询,但参数不同:

This is a pretty much the same query but with a different parameters:

MATCH (parentD)-[:CONTAINS]->(childD:Decision)-[ru:CREATED_BY]->(u:User) 
WHERE id(parentD) = 415406 
MATCH (childD)<-[:SET_FOR]-(filterValue416423:Value)-[:SET_ON]->(filterCharacteristic416423:Characteristic) 
WHERE id(filterCharacteristic416423) = 416423 
WITH filterValue416423, childD, ru, u 
WHERE ('Adobe RGB' IN filterValue416423.value ) OR ('ECI RGB' IN filterValue416423.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue416273:Value)-[:SET_ON]->(filterCharacteristic416273:Characteristic) 
WHERE id(filterCharacteristic416273) = 416273 WITH filterValue416273, childD, ru, u 
WHERE  (filterValue416273.value >= 4) AND (filterValue416273.value <= 53)  
MATCH (childD)<-[:SET_FOR]-(filterValue415431:Value)-[:SET_ON]->(filterCharacteristic415431:Characteristic) 
WHERE id(filterCharacteristic415431) = 415431 WITH filterValue415431, childD, ru, u 
WHERE  ('Compact' IN filterValue415431.value ) 
  OR ('Compact SLR' IN filterValue415431.value ) 
  OR ('Large SLR' IN filterValue415431.value ) 
  OR ('Rangefinder-style mirrorless' IN filterValue415431.value ) 
  OR ('SLR-like (bridge)' IN filterValue415431.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue415441:Value)-[:SET_ON]->(filterCharacteristic415441:Characteristic) 
WHERE id(filterCharacteristic415441) = 415441 WITH filterValue415441, childD, ru, u 
WHERE  ('Brass' IN filterValue415441.value ) 
  OR ('Carbon fiber' IN filterValue415441.value )  
  OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN [415414, 415415, 415412, 415426, 415411]  
WITH childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
WITH ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes  
ORDER BY  weight DESC 
SKIP 0 LIMIT 10 
RETURN ru, u, childD AS decision, weight, totalVotes, 
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | 
  {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
[ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) | 
  {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1:Value)-[:SET_FOR]->(childD) | 
  {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics

密码版本:CYPHER 3.1,计划程序:COST,运行时:INTERPRETED. 390毫秒内646192总数据库命中率.

Cypher version: CYPHER 3.1, planner: COST, runtime: INTERPRETED. 646192 total db hits in 390 ms.

已更新

这是:schema

Indexes
   ON :Characteristic(lowerName) ONLINE
   ON :CharacteristicGroup(lowerName) ONLINE
   ON :Criterion(lowerName) ONLINE
   ON :CriterionGroup(lowerName) ONLINE
   ON :Decision(lowerName) ONLINE
   ON :FlagType(name) ONLINE (for uniqueness constraint)
   ON :HistoryValue(originalValue) ONLINE
   ON :Permission(code) ONLINE (for uniqueness constraint)
   ON :Role(name) ONLINE (for uniqueness constraint)
   ON :User(email) ONLINE (for uniqueness constraint)
   ON :User(username) ONLINE (for uniqueness constraint)
   ON :Value(value) ONLINE

Constraints
   ON ( flagtype:FlagType ) ASSERT flagtype.name IS UNIQUE
   ON ( permission:Permission ) ASSERT permission.code IS UNIQUE
   ON ( role:Role ) ASSERT role.name IS UNIQUE
   ON ( user:User ) ASSERT user.email IS UNIQUE
   ON ( user:User ) ASSERT user.username IS UNIQUE

已更新

我已经按照以下答案中的建议对查询进行了优化:

I have optimized the query as suggest at the answer below:

MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = 415406 
MATCH (childD)<-[:SET_FOR]-(filterValue416423)-[:SET_ON]->(filterCharacteristic416423) 
WHERE id(filterCharacteristic416423) = 416423 
WITH DISTINCT filterValue416423, childD 
WHERE ('Adobe RGB' IN filterValue416423.value ) OR ('ECI RGB' IN filterValue416423.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue416273)-[:SET_ON]->(filterCharacteristic416273) 
WHERE id(filterCharacteristic416273) = 416273 
WITH DISTINCT childD, filterValue416273  
WHERE  (filterValue416273.value >= 4) AND (filterValue416273.value <= 53)  
MATCH (childD)<-[:SET_FOR]-(filterValue415431)-[:SET_ON]->(filterCharacteristic415431) 
WHERE id(filterCharacteristic415431) = 415431 
WITH DISTINCT childD, filterValue415431 
WHERE  ('Compact' IN filterValue415431.value ) 
  OR ('Compact SLR' IN filterValue415431.value ) 
  OR ('Large SLR' IN filterValue415431.value ) 
  OR ('Rangefinder-style mirrorless' IN filterValue415431.value ) 
  OR ('SLR-like (bridge)' IN filterValue415431.value )  
MATCH (childD)<-[:SET_FOR]-(filterValue415441)-[:SET_ON]->(filterCharacteristic415441) 
WHERE id(filterCharacteristic415441) = 415441 
WITH DISTINCT childD, filterValue415441 
WHERE  ('Brass' IN filterValue415441.value ) 
  OR ('Carbon fiber' IN filterValue415441.value )  
  OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN [415414, 415415, 415412, 415426, 415411]  

WITH DISTINCT * MATCH (childD)-[ru:CREATED_BY]->(u:User)  
WITH DISTINCT childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
WITH DISTINCT ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes  
ORDER BY  weight DESC 
SKIP 0 LIMIT 10 
RETURN ru, u, childD AS decision, weight, totalVotes, 
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | 
  {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
[ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) | 
  {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1)-[:SET_FOR]->(childD) | 
  {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics

配置文件输出:

使用DISTINCT childD时,查询工作相当缓慢,虽然没有改善,但仍然远远不够完善

With DISTINCT childD the query works pretty slow, without much better but stil so far from perfect

再尝试一次

PROFILE MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = 415406 
MATCH (childD)<-[:SET_FOR]-(filterValue416423)-[:SET_ON]->(filterCharacteristic416423)
USING JOIN ON childD
WHERE id(filterCharacteristic416423) = 416423
AND ('Adobe RGB' IN filterValue416423.value ) OR ('ECI RGB' IN filterValue416423.value )
WITH DISTINCT childD
MATCH (childD)<-[:SET_FOR]-(filterValue416273)-[:SET_ON]->(filterCharacteristic416273) 
USING JOIN ON childD
WHERE id(filterCharacteristic416273) = 416273 AND (filterValue416273.value >= 4) AND (filterValue416273.value <= 53)
WITH DISTINCT childD  
MATCH (childD)<-[:SET_FOR]-(filterValue415431)-[:SET_ON]->(filterCharacteristic415431) 
USING JOIN ON childD
WHERE id(filterCharacteristic415431) = 415431
AND ('Compact' IN filterValue415431.value ) 
  OR ('Compact SLR' IN filterValue415431.value ) 
  OR ('Large SLR' IN filterValue415431.value ) 
  OR ('Rangefinder-style mirrorless' IN filterValue415431.value ) 
  OR ('SLR-like (bridge)' IN filterValue415431.value )
WITH DISTINCT childD
MATCH (childD)<-[:SET_FOR]-(filterValue415441)-[:SET_ON]->(filterCharacteristic415441) 
USING JOIN ON childD
WHERE id(filterCharacteristic415441) = 415441
AND ('Brass' IN filterValue415441.value ) 
  OR ('Carbon fiber' IN filterValue415441.value )  

OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN [415414, 415415, 415412, 415426, 415411]  

WITH DISTINCT * MATCH (childD)-[ru:CREATED_BY]->(u:User)  
WITH DISTINCT childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
WITH DISTINCT ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes  
ORDER BY  weight DESC 
SKIP 0 LIMIT 10 
RETURN childD

推荐答案

查询的主要问题是,您基本上要进行大量检查,而行却很疯狂.因此,这里有一些技巧,可以减少每个MATCH生成多少行.

The main problem with your query, is that you are basically doing a lot of checks, with rows running wild. So here are some tips to reduce how many rows you are generating at each MATCH.

1)除非需要重复,否则请使用WITH DISTINCT而不是WITH. WITH可以创建重复的行(因为您只切断一列),并且您处理的每个重复行都浪费时间和额外的数据库命中. (即,您放下的每个过滤器列都会添加重复的行)

1) Unless you NEED duplicates, use WITH DISTINCT instead of just WITH. WITH can create duplicate rows (because you only cut off a column), and every duplicate row you process is wasted time and extra DB hits. (Namely, every filter column you drop adds duplicate rows)

2):Value.value重载.它没有语义,甚至不能保证该值是任何类型.这意味着每次:Value检查都必须走出去,并触摸一堆与搜索内容无关的:Value节点.因此,随着附加的:Value节点数量的增加,找到正确的节点的成本变得更高(如果可以对其进行索引,则成本会降低,以便可以找到正确的:Value并查看其连接的对象如果您无法更改正在使用的架构,这无济于事,按架构,我指的是您的数据/关系的设置方式.

2) :Value.value is overloaded. It has no semantic meaning, and the value isn't even guaranteed to be any kind of type. That means every :Value check has to go out and touch a bunch of :Value nodes that have nothing to do with what your searching for. So as the number of attached :Value nodes increases, the more expensive it becomes to find the right one (This is less expensive if it could be indexed, so that it could just find the right :Value, and see what it is connected to. This doesn't help if you can't change the schema you're working with, and by schema, I mean how your data/relationships are setup).

3)仅检查您需要检查的内容.说(a:A)-[:TO]->(b:B)似乎更有效,但是如果所有[:TO]都从:A到:B,Neo4j现在必须验证第一个节点是:A,第二个节点是:B. Cypher不知道隐式的真实情况,因此它必须执行检查,但是这些冗余检查中的每一个都必须走出去并击中数据库的每一行.所以最好说(a)-[:TO]->(b).

3) Only check what you need to check. It might seem more efficient to say (a:A)-[:TO]->(b:B), but if all [:TO] are from :A to :B, Neo4j now has to verify that the first node is an :A and the second node is a :B. Cypher doesn't know what is implicitly true, so it has to do the check, but each of these redundant checks has to go out and hit the DB for every row. So it is better to say (a)-[:TO]->(b).

4)限制变量范围.在这里,您在开头匹配-[ru:CREATED_BY]->(u:User),但不要在结尾使用它,没有过滤器.这会将每个行中的行数乘以-[ru:CREATED_BY]->(u:User)的数目,即必须在进一步的匹配中检查ALL.除非-[ru:CREATED_BY]->(u:User)以某种方式极大地限制了匹配的决策(或者每个决策只能有一个决策),请最后匹配此支持信息.

4) Limit variable scope. Here, you match -[ru:CREATED_BY]->(u:User) at the beginning but than don't use it til the end, with no filters. This multiplies how many rows you have by the number of -[ru:CREATED_BY]->(u:User) on each decision, that ALL have to be checked in the further matches. Unless -[ru:CREATED_BY]->(u:User) somehow greatly limits the matched decisions (or there can only be one per decision), match this support information at the end.

5)将过滤器从最强到最弱(如果可以)排序.尽早切割多行.

5) Order your filters from strongest to weakest (if you can). to cut as many rows as early as possible.

6)技巧以最小化行.拔出的每一行使得查询中的以下步骤必须更加艰苦,因此请尽量减少查询中的行.如果您使用OR来组合不相关但相似的列查询(例如,所有条件A的组织或条件B的组织),并且两个查询的工作对另一半来说使事情变得更加昂贵,那么使用UNION可能会更好合并较小,更快的查询的结果(UNION可以并行运行直至合并结果).请注意,[1,2,3]中的WHERE org.id之类的简单查询仍比UNION快,因为所有工作都可以在一次查询中完成.

6) Tricks to minimize rows. Each row pulled up makes the following steps in the query have to work that much harder, so minimize rows in queries. If you are using OR to combine unrelated, but similar columns queries (like all orgs with conditions A or orgs with conditions B) and the work of the two queries just make things more expensive for the other half, it might be better to use UNION to combine the results of smaller, faster queries (and UNION can run in parallel up to the merge results). Note that simple queries like WHERE org.id in [1,2,3] are still faster than UNION, since the work can all be done in one lookup.

除了并集之外,如果要收集未过滤的节点,则可以使用collect(column)将重复项"减少到1行,然后使用UNWIND(列)作为末尾的列查询以获取您的行! (这里的列指的是变量名)

Aside from union, if you are collecting nodes that you don't filter on, you can use collect(column) to reduce 'duplicates' down to 1 row, and than UNWIND (column) as column at the end of the query to get your rows back! (column here referring to variable name)

7)在1个节点上进行了很多过滤? Cypher已使用提示!提示USING JOIN ON column告诉Cypher,使用更多起始叶子并加入它们,可能会更有效地进行此匹配.因此,在每个匹配项上使用USING JOIN ON childD会告诉Cypher并行执行所有过滤器,并使用所有过滤器的重叠行.请注意,使用USUS只是在告诉Cypher相信我,如果我们尝试这样做,这样做会更快",如果您输入错了,这实际上会使查询变得更糟. (不过,使用JOIN对于使大型查询更加并行来说应该会很有用)

7) Doing a lot of filters on 1 node? Cypher has USING hints for that! The hint USING JOIN ON column tells Cypher that it will probably be more efficient doing this match with more starting leafs and joining them. So using USING JOIN ON childD on each match will tell Cypher to do all the filters in parallel, and use the overlapping rows of all of them. Note that USINGs are just you telling Cypher "trust me, this should go faster if we try doing this" which can actually make the query worse if you are wrong. (USING JOIN should be useful though for making large queries more parallel though)

更新:
首先,关于node.id ="constant" AND node.value ="constant" OR node.id ="constant2" AND node.value ="constant2" vs node.value = map [node.id]的注释.第一个查询能够对节点查找进行节点过滤,而后一个查询必须对已经查找过的所有节点进行过滤.如果没有对该查找进行先前的过滤,则意味着该映射必须拉入所有节点.虽然地图提供了一定程度的(可争论的)简单性/灵活性,但这是过滤节点效率最低的方法之一.

UPDATE:
First, a note on node.id = "constant" AND node.value = "constant" OR node.id = "constant2" AND node.value = "constant2" vs node.value = map[node.id]. The first query is able to do node filtering on node lookup, while the later has to filter through all of the nodes that where already looked up. Without previous filtering on that lookup, that means the map has to pull in all nodes. While the map offers some level of (arguable) simplicity/flexibility, it is one of the least efficient ways to filter nodes.

第二,现在查询的最大问题是:Value超重载,您无法通过ID来找到它. :Value应该是一个关系,或者具有索引ID字段,这样您就不必触摸ALL<-[:SET_FOR]-和-[:SET_ON]->.我认为使用Join提示至少可以使SET_FOR的优先级更高,这似乎是两者中效率更高的一个.

Second, The big problem with your query now, is the :Value is super overloaded, and you aren't finding it by ID. :Value should be a relationship, or have an indexed ID field so that you don't have to touch ALL <-[:SET_FOR]- and -[:SET_ON]->. Using the Join hint I think will at least make SET_FOR higher priority, which appears to be the more efficient of the two.

这是我尝试更有效地重写PROFILE查询的方法. (v1)

Here is my attempt to rewrite the PROFILE query more efficiently. (v1)

MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = 415406 
MATCH (childD)<-[:SET_FOR]-(filterValue416423)-[:SET_ON]->(filterCharacteristic416423)
USING JOIN ON childD
WHERE id(filterCharacteristic416423) = 416423
WHERE ('Adobe RGB' IN filterValue416423.value ) OR ('ECI RGB' IN filterValue416423.value )
WITH DISTINCT childD
MATCH (childD)<-[:SET_FOR]-(filterValue416273)-[:SET_ON]->(filterCharacteristic416273) 
USING JOIN ON childD
WHERE id(filterCharacteristic416273) = 416273 AND (filterValue416273.value >= 4) AND (filterValue416273.value <= 53)
WITH DISTINCT childD  
MATCH (childD)<-[:SET_FOR]-(filterValue415431)-[:SET_ON]->(filterCharacteristic415431) 
USING JOIN ON childD
WHERE id(filterCharacteristic415431) = 415431
WHERE ('Compact' IN filterValue415431.value ) 
  OR ('Compact SLR' IN filterValue415431.value ) 
  OR ('Large SLR' IN filterValue415431.value ) 
  OR ('Rangefinder-style mirrorless' IN filterValue415431.value ) 
  OR ('SLR-like (bridge)' IN filterValue415431.value )
WITH DISTINCT childD
MATCH (childD)<-[:SET_FOR]-(filterValue415441)-[:SET_ON]->(filterCharacteristic415441) 
USING JOIN ON childD
WHERE id(filterCharacteristic415441) = 415441
WHERE  ('Brass' IN filterValue415441.value ) 
  OR ('Carbon fiber' IN filterValue415441.value )  

OPTIONAL MATCH (childD)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) 
WHERE id(c) IN [415414, 415415, 415412, 415426, 415411]  

WITH DISTINCT * MATCH (childD)-[ru:CREATED_BY]->(u:User)  
WITH DISTINCT childD, ru, u, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes 
WITH DISTINCT ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes  
ORDER BY  weight DESC 
SKIP 0 LIMIT 10 
RETURN ru, u, childD AS decision, weight, totalVotes, 
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | 
  {entityId: id(entity),  types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups, 
[ (parentD)<-[:DEFINED_BY]-(c1:Criterion)<-[:VOTED_ON]-(vg1:VoteGroup)-[:VOTED_FOR]->(childD) | 
  {criterionId: id(c1),  weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria, 
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[:SET_ON]-(v1)-[:SET_FOR]->(childD) | 
  {characteristicId: id(ch1),  value: v1.value, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics

这篇关于Neo4j Cypher查询结构和性能优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆