Jacek Dominiak
Jacek Dominiak

Reputation: 877

how to normalize value in neo4j cypher

Given the set of results, I would like to normalize one value.

Example of ideal world query:

match (c)<-[:WORKS_FOR]-(u)-[:KNOWS]->(s)
where s.label = "Test"
with u as users
match (users)-[com:SEND]-(otherUsers)
with  users, sum(com.count) as messages
return users, messages / max(messages)

How to I get the max(messages) from across the users? UNWIND maybe?

Upvotes: 0

Views: 1012

Answers (1)

InverseFalcon
InverseFalcon

Reputation: 30397

We can improve this one a bit.

For one, you'll want to use at least one label here, so you avoid performing all node scans. Hopefully you're using labels when creating your nodes. If not, definitely start, unlabeled nodes will be non-performant for use in most queries, since you'll be using all node scans.

Also, for fast entry into the local graph, a label on s would be helpful, and an index on that label and its label property (which isn't the same as an actual label, just so you're aware).

Next, if you want to ensure a node has at least one relationship, it's better to use a WHERE for that rather than including it in the match. This can also reduce cardinality issues (say in case a user works for more than one company), which could multiply your results and the amount of subsequent work (as well as throw off other parts of your query).

As for how to aggregate max(messages) across all users, you'll need to aggregate the other variables as well, which is a little annoying, but no way around it.

Also, I prefer using singular for most variables, and only use plurals for collections, that can help avoid confusion.

Here's an example with the changes provided (assuming s is also a :User and that there's an index on :User(label)):

match (user:User)-[:KNOWS]->(s:User)
where s.label = "Test" and ()<-[:WORKS_FOR]-(user)
match (user)-[com:SEND]-()
with  user, sum(com.count) as messages
with collect({user:user, messages:messages}) as usersInfo, 1.0 * max(messages) as total
unwind usersInfo as userInfo
return userInfo.user as user, userInfo.messages / total as percentage

Upvotes: 1

Related Questions