Retrieve nodes based on relationships count with an exception

Hi,
I have 100000 nodes "Person" and 1000 "Company"
i have relationship types "CEO" , "CTO", "ACCOUNTANT", "WORKER", ....
A person can be related to several companies with all type of rels...
Now, i need to find the top 10 Persons with most connections Except "ACCOUNTANT"
for example:
John is a CEO in 4 companies, CTO in 10 companies and ACCOUNTANT in 20 companies
Jane is CEO in 2 companies, CTO in 10 companies and ACCOUNTANT in 40 companies
We see that Jane has more relationships than John but... if we ignore "ACCOUNTANT" , John has more relationships than Jane
The query should return the top 10 Persons with all relationships (except "ACCOUNTANT") to the companies (including the Company nodes)
Thanks

if I get you right, what you need is the top 10 of a list of number of relations between a person and a company (excluding accountant relations)

did not test but it should be something like

MATCH (p:Person)-[r:CEO|CTO|WORKER]-(:Company)
WITH p, size(collect(r)) as nbRel
return p order by nbRel desc limit 10

Try this. The relationship expression syntax requires version 5.

Match (n:Person)
with n, count{(n)-[:!ACCOUNTANT]-(:Company)} as cnt
Order by cnt desc
Limit 10
Return n

hi Gary, never saw the count{} syntax, can you please point to a documentation reference about it ?

Thanks, but i have more than 20 relationship types' and i don't want to specify all of them except ACCOUNTANT, i want to specify only the exclusion

then use the syntax Gary suggested : [:!ACCOUNTANT]

Hi, Thanks, but it returns only the persons, and i already managed to do it.
What I need to return is the persons , the companies and all the relationships between them
Thanks

MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company)
WITH p, size(collect(r)) as nbRel,collect(distinct type(r)) as rels,collect(distinct c.name) as cies
return p.name,rels,cies order by nbRel desc limit 10

or if you need the nodes


MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company)
WITH p, size(collect(r)) as nb Relorder by nbRel desc limit 10
MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company) return *

You should not have to match twice.

MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company)
WITH p, collect(c) as companies
ORDER BY size(companies) DESC
LIMIT 10
RETURN p as person, companies 

It’s a subquery expression. There are three: count, exists, collect.

1 Like

you do not return relationships

What I need to return is the persons , the companies and all the relationships between them

oops, try this instead:

MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company)
WITH p, collect(c) as companies, collect(r) as relationships
ORDER BY size(companies) DESC
LIMIT 10
RETURN p as person, companies, relationships

or, if you want the relationships related to its company:

MATCH (p:Person)-[r:!ACCOUNTANT]-(c:Company)
WITH p, collect({company:c, relationship:r}) as companies
ORDER BY size(companies) DESC
LIMIT 10
RETURN p as person, companies
1 Like

Thank, it's working...
Now, i need to find connections between persons with 2-4 hops of specific relationships or any relationships...
i tried to add this before "RETURN":
MATCH (p)-->(:Company)--(p:Person)
and it doesn't work
Thanks

I think your issue is that your match has 'p' related to 'p', which would be a loop. Don't put 'p' in the end node, as this constrains the node to be the same as the start node 'p', but with a further constraint of being a Person node.

If you want paths that are from 2 to 4 hops between node 'p' and another person, then try the following:

MATCH (p)-[*2..4]-(:Person)

If you provide the entire query and what is wrong, I can try to help further.

Thanks,

To be more specific:
I want to find out if there is a connection between John and Jane based on relationships to companies with 2-4 hops...
I tried this:
MATCH (p {idNumber: 1111111})-[*2..4]-(:Person{idNumber:33333333})RETURN *
Doesn't work

If you are only interested in the existence of the relationship you should use the ‘exits’ subquery expression. This was added in version 5.4 or 5.6 or there about. You can verify in the docs. It allows you to execute a complicated query and will return true or false corresponding to the query producing at least one record. If the query is a one line match, then you can use the exists function. It is not new.

The following is an example using the exists function since your query consists of a single match.

MATCH(p:Person{number:111111})
RETURN  p, exists( (p)-[*2..4]-(:Person{idNumber:33333333}) ) as exists

Thanks,

But i need the 2 persons and the relationships between them, so i can see how they connected to each other

Try this

MATCH(p:Person{idNumber:111111})
MATCH(m:Person{idNumber:33333333})
MATCH path=(p)-[*2..4]-(m)
RETURN  p, m, relationships(path)

I am kinda lost on where we stand with your original query.