Finding unique values of a node property - neo4j

I have a neo4j database with several nodes each having many properties. I am trying to find a list of unique values available for each property.
Currently, I can search for nodes that have a certain value 'xxx' with a query in this manner below however, I want to find all the unique values 'xxx','yyy', etc. that may exist in all the nodes in my database.
match (n:Db_Nodes) where n.stringProperty = "xxx" return n
How should I go about structuring the query desired?

You can use the DISTINCT Clause to return all the unique values for this property.
There are two ways to get all the values:
Get all the values in a list. Here result will be one single record with all the unique values in the form of a list.
MATCH (n:Db_Nodes) RETURN COLLECT(DISTINCT n.stringProperty) as propertyList
Get one value per record. Here multiple records will be returned(One per unique property value).
MATCH (n:Db_Nodes) RETURN DISTINCT n.stringProperty

Related

Can we make cypher field query Case-Insensitive

It may seem duplicate of this but it is not. Can we make cypher query case insensitive based on fields. I know we can use regex for values but we need it based on fields.
e.g.
MATCH (c:customer) WHERE c.CUSTOMERNUMBER = '1088' RETURN c
Above query returns a result, but following does not
MATCH (c:Customer) WHERE c.CustomerNumber = '1088' RETURN c
Here lable Customer and property CustomerNumber are having different cases.
You can use PROPERTIES to get a map representation of a node, and then use KEYS so that you can iterate over them. Because "Name", "NAME", and "Prop1" are all equally unique property names, and they can all or none exist, as far as the DB is concerned. You will have to iterate every property of the node to find a field that matches your criteria.
MATCH (n)
WHERE ANY(key in KEYS(n) WHERE lower(key)="name" AND n[key]="Neo")
RETURN n
This is more flexible than simple case insensitivity, but it is also expensive.

Why don't some query results have graph representation in Neo4j?

In the Neo4j Browser, I performed one query as follows:
match (subject:User {name:{name}})
match (subject)-[:works_for]->(company:Company)<-[:works_for]-(person:User),
(subject)-[:interested_in]->(interest)<-[:interested_in]-(person)
return person.name as name, count(interest) as score,
collect(interest.name) as interests order by score DESC
The result only has the "table" and "text" views, without the "graph". Normally, a query can generate a subgraph. Right?
If you look at your return, you're not returning any actual nodes or relationships. You're returning property values (strings), counts (longs), and collections of strings. If you returned person instead you would probably be able to see a graphical result, as the return would include data (id, labels, properties) that could be used to display graph elements.

How to return single node with Multiple match for different labels in neo4j?

I am using neo4j 3.2.x. What I am try to do is write a query that will update relation between two nodes (User and Gender) and return single User node with InterestedInGender property pulled from relation as array. There is a problem with the below query as right now it returns multiple records with single value for interestedInGender. Relations are created properly but when returning data it is returning multiple records. I just want to return User node. Is there any way we can fix this query to just return single user node.
MATCH (u:User {_id:"1234"})
MATCH (ig:Gender) WHERE ig.value IN ["male", "female"]
WITH u, ig
OPTIONAL MATCH (u)-[igr:INTERESTED_IN_GENDER]->()
DELETE igr
with u, ig
MERGE (u)-[:INTERESTED_IN_GENDER]->(ig)
RETURN u{
._id,
interestedInGender: [(u)-[:INTERESTED_IN_GENDER]->(ig:Gender) | ig.value]
}
The reason you're getting multiple records (rows) is because your ig match to gender matches to two :Gender nodes...two rows where both rows have the same u node, but different ig nodes. That cardinality remains throughout the rest of your query, and so you get two rows back.
You need to shrink the cardinality of u back down to 1 after you MERGE the relationship, so add this after your MERGE but before your RETURN:
WITH distinct u

How to filter neo4j nodes by the properties and (optionally) IDs of connected nodes?

There is a :ActivityRecord node in neo4j DB, intended for holding audit records in the database. Trying to filter them by various optional parameters, including :Application and :Tenant organization where activity was performed.
Cypher query
MATCH (ac:ActivityRecord)-[:GENERATED_IN]->(t:Tenant),
(ac:ActivityRecord)-[:GENERATED_IN]->(a:Application)
WHERE ac.objectId=coalesce(null, ac.objectId) AND ac.type=coalesce(null, ac.type)
AND ID(t)=coalesce(null, ID(t)) AND ac.changes =~ ".*test.*"
RETURN ac
ORDER BY ac.timestamp
returns no records, whereas query with OPTIONAL MATCH does not filter them appropriately (returns all records of :ActivityRecord type). How to make this query work in case ID(t)=null or ID(a)=null?
[UPDATE]
Clarification: actually, I am calling the below query from the application with appropriate parameters inserted to their places
MATCH (ac:ActivityRecord)-[:GENERATED_IN]->(t:Tenant),
(ac:ActivityRecord)-[:GENERATED_IN]->(a:Application)
WHERE ac.objectId=coalesce({objectId}, ac.objectId)
AND ac.type=coalesce({type}, ac.type)
AND ID(t)=coalesce({tenantId}, ID(t))
AND ID(a)=coalesce({applicationId}, ID(a))
AND ac.changes =~ ".*test.*"
RETURN ac
ORDER BY ac.timestamp
Because the parameters are optional, I need to handle situation when they are not specified. So I decided to use ID(t)=coalesce({tenantId}, ID(t)) for this case, what will be equal to ID(t)=ID(t) in case the tenantId param is not specified (so we just don't filter by this parameter, what I was going to actually achieve). The first query I specified was just a degraded case of the above query.
So the goal is to compose the query which will filter nodes by their attributes and by IDs of connected nodes (only if params are not null in the query).

Neo4j Cypher finding the average of node properties which have another property in common

I have a "Gene" Label/node type with properties "value" and "geneName"
I have a separate Label/node type called Pathway with property "
I want to go through all the different geneName's and find the average of all the Gene's value with that Gene name. I need all those Gene's displayed as different rows. Bearing in mind I have a a lot of geneName's so I can't name them all in the query. I need to do this inside a certain Pathway.
MATCH (sample)-[:Measures]->(gene)-[:Part_Of]->(pathway)
WHERE pathway.pathwayName = 'Pyrimidine metabolism'
WITH sample, gene, Collect (distinct gene.geneName) AS temp
I have been trying to figure this out all day now and all I can manage to do is retrieve all the rows of geneNames. I'm lost from there.
RETURN extract(n IN temp | RETURN avg(gene.value))
Mabye?
This query should return the average gene value for each distinct gene name:
MATCH (sample)-[:Measures]->(gene)-[:Part_Of]->(pathway:Pathway)
WHERE pathway.pathwayName = 'Pyrimidine metabolism'
RETURN sample, gene.geneName AS name, AVG(gene.value) AS avg;
When you use an aggregation function (like AVG), it automatically uses distinct values for the non-aggregating values in the same WITH or RETURN clause (i.e., sample and gene.geneName in the above query).
For efficiency, I have also added the label to the pathway nodes so that neo4j can start off by scanning just Pathway nodes instead of all nodes. In addition, you should consider creating an index on :Pathway(pathwayName), so that the search for the Pathway is as fast as possible.

Resources