Hello,
I have a query that matches two labels and returns them sorted by name, but it can be slow for some accounts.
We are using Neo4j Aura and Neo4j version is 4.3.3
This is some sample of database structure:
(:User { firstName: "Name", "lastName": "Surname" })-[:SHARED_WORKSPACE]->(:Workspace)
(:Workspace)-[:HAS_CONTACT]->(:Contact { name: "Name Surname" })
The goal is to return both :User and :Contact labels sorted ASC by name
Current query (simplified):
MATCH (workspace:Workspace { id: "uuid" })
MATCH (contact)
WHERE (contact:User OR contact:Contact)
AND (
EXISTS ((contact)-[:SHARED_WORKSPACE]->(workspace))
OR EXISTS ((workspace)-[:HAS_CONTACT]->(contact))
)
AND (contact.status = "CONFIRMED" OR contact.status IS NULL)
MATCH (creator:User { id: contact.created_by })
RETURN DISTINCT contact, workspace, creator
ORDER BY TOLOWER(COALESCE(contact.firstName + ' ' + contact.lastName, contact.name)) ASC, contact.id
SKIP 0
LIMIT 100
So for some workspaces that query can take between 3-5 seconds, which is too long. The goal is to make execution time less than 2 seconds.
When I profile, I can see that it starts from NodeByLabelScan on the whole database, while we only care about the labels that matches the relationships with matched workspace
I've tried different ways to change the query so it matches both labels with relationships, for example:
MATCH (workspace:Workspace { id: "uuid" })
OPTIONAL MATCH (contact)-[:SHARED_WORKSPACE]->(workspace) WHERE (contact:User OR contact:Contact)
OPTIONAL MATCH (workspace)-[:HAS_CONTACT]->(contact) WHERE (contact:User OR contact:Contact)
....
But it this case it will only match single label, depending which OPTIONAL MATCH will be first, either :User or :Contact.
Also it seems that ordering with COALESCE is not very productive:
ORDER BY TOLOWER(COALESCE(contact.firstName + ' ' + contact.lastName, contact.name)) ASC, contact.id
Unfortunately can't change the date, and User and Contacts has a bit different properties, so doing this to order by name.
Any suggestions?
Thanks