简体   繁体   中英

How can I call this APOC procedure selectively? (only on a subset of nodes)

I have a Neo4J database with a number of nodes of label com. These nodes contain a key property - which uniquely groups them in the fashion that I want. They also have a timestamp property, as well as a number of other integer properties.

Here's the issue I'm facing: I want to use the APOC graph grouping procedure to aggregate these nodes together, based on their key properties. However, I want to do so selectively - such that I only aggregate the nodes if their timestamp property meets a provided time window.

I have tried to MATCH and filter the nodes with a WHERE clause based on their timestamp, but I am unable to specifically pass those nodes to the nodes.group procedure. Basically, I need to figure out how to CALL nodes.group only on a specific subset of nodes. I'd appreciate any help.

Here is the CALL I'm performing:

CALL apoc.nodes.group(['com'], ['key'], [{val1: 'sum', val2: 'sum', val3: 'sum',' time_start: 'collect'}]) YIELD node

As I mentioned above, I tried performing a

MATCH (c:com) WHERE c.time_start >= datetime('2020-12-16T21:45:05Z')

...prior to the procedure and then chaining queries, but it did not work.

The procedure still got called on ALL nodes of com relationship, not just the ones I filtered.

The procedure itself does not allow you to pass such filters. There are however two possibilities to circumvent this:

  1. build the virtual graph yourself with vNode and vRelationship
  2. set a temporary label after your node selection and group on that

I will focus on option 2:

Take the following graph as an example:

UNWIND range(1, 200) AS i
CREATE (n:com)
SET n.timestamp = i, 
n.key = apoc.coll.randomItem(items)

And let's say I have an hypothetical window to use that is 30 to 70 , I can find only the nodes matching my window predicate:

WITH [30, 70] AS window
MATCH (n:com) 
WHERE n.timestamp > window[0] 
AND n.timestamp < window[1]
RETURN count(n)

╒══════════╕
│"count(n)"│
╞══════════╡
│39        │
└──────────┘

Before jumping in the grouping query, I just want to show that you can set a label and remove it in the same query, using the predicate.

WITH [30, 70] AS window
MATCH (n:com) 
WHERE n.timestamp > window[0] 
AND n.timestamp < window[1]
SET n:temporary
WITH count(n) AS doSomething
MATCH (n:temporary)
REMOVE n:temporary
WITH count(*) AS break, doSomething
RETURN doSomething

The last WITH count(*) is necessary to not return one row per temporary node.

Now, using this logic, we can:

  1. MATCH nodes using the window predicate
  2. Assign them a new temporary label
  3. Use apoc.nodes.group on the temporary label instead
  4. Remove the temporary label
  5. Return the grouped nodes
WITH [30, 70] AS window
MATCH (n:com) WHERE n.timestamp > window[0] AND n.timestamp < window[1]
SET n:temporary
WITH window, count(*) AS x
CALL apoc.nodes.group(['temporary'], ['key'], null, {})
YIELD node, relationship
WITH collect(node) AS elements
MATCH (n:temporary) REMOVE n:temporary
WITH count(*) AS break, elements
UNWIND elements AS element
RETURN element

╒════════════════════════╕
│"element"               │
╞════════════════════════╡
│{"count_*":6,"key":"f"} │
├────────────────────────┤
│{"count_*":6,"key":"e"} │
├────────────────────────┤
│{"count_*":12,"key":"d"}│
├────────────────────────┤
│{"count_*":1,"key":"c"} │
├────────────────────────┤
│{"count_*":5,"key":"b"} │
├────────────────────────┤
│{"count_*":9,"key":"a"} │
└────────────────────────┘

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM