cancel
Showing results for 
Search instead for 
Did you mean: 

Need to optimize Neo4j Query

Hi,
I am creating a social media app whose back-end is Neo4j. Here, I want to fetch friends activities on user's homepage. I have put a limit of 10 activities per scroll.
This is my current Neo4j Query:

MATCH (m:Person { id: '58c1370350b91a0005be0136'})-[:FOLLOWS*1..1]->(f:Person)-[:HAS_ACTIVITY]->(la:Activity)-[:NEXT*0..]->(act:Activity)
WHERE act.verb IN ['post' ,'post_media_item' ,'watch_activity'] 
RETURN f, act ORDER BY act.published DESC LIMIT 10

In the above query user are depicted by Person node and User-feed is depicted by Activity node. "m" is current user whose friends "f" are depicted by the relationship "Follows". Activity for each user are interlinked with the relationship "NEXT" and are linked with Person node with relationship "HAS_ACTIVITY". It is intentional to keep maximum hops blank as a Person can have any number of activities.

For this query as Friend List of a person grows, so does the overall query execution time.
Currently for a user having 50 friends the time taken is 3-5 seconds.
I have to perform further aggregation from the result of this query which takes query execution time to 7-10 seconds.

Please find Attached screenshot of PROFILE and EXPLAIN:


How can I optimize my Cypher query so that I get quickest result irrespective of number of friends?

Neo4j Version used: 3.0.6

1 REPLY 1

Update your Neo4j version first, current is 4.2.2

then you can try the following:

  1. use parameters for your query
  2. turn the act_verb into additional labels on Activity
  3. create an index on :Activity(published) so that index is used to drive the right side
  4. use two indexes from either side that meet in the middle with USING JOIN
MATCH (m:Person { id: $id})-[:FOLLOWS]->(f:Person)
MATCH (f)-[:HAS_ACTIVITY]->(la:Activity)-[:NEXT*0..]->(act:Activity)
USING JOIN ON f
WHERE act.published > 0 AND (act:Watch OR act:Post OR act:PostMedia)
RETURN f, act ORDER BY act.published DESC LIMIT 10

I did something similar for LDBC

match (p:Person)<-[:HAS_MEMBER]-(f)-[:CONTAINER_OF]->(m:Message)
using join on f
where p.id = 4398046511714 and m.creationDate>0
return m order by m.creationDate desc limit 20