Cypher Sleuthing: How to Get Data Types of Properties in Neo4j
- 4 minutes read - 834 wordsIt’s been awhile since I wrote a Cypher Sleuthing post, but I’m back with a new one! This time, I’m going to show you how to find the data types of properties in Neo4j.
I frequently want to find out the data type of a property so that I can map it in an application (in Java). I can never remember off the top of my head, and when I Google the question, the results are often outdated (here’s the answer post, but the syntax is old). So, I end up doing a mix of searching docs and Slack messages (who has time for that?!) and trial and error. :P
This blog post hopes to shortcut my lookup process for "future me", as well as maybe help you out too!
Cypher data types
There are many data types available in Neo4j, and most of them match up to types available in other technologies. The full list is available in the Cypher documentation.
Standard, simple data types are most often used, including String
, Integer
, Float
, Boolean
, and DateTime
. The mapping for Cypher to Java types is pretty straightforward, but every once in awhile, I get an ugly mapping error because I didn’t verify the type conversion.
How can we verify whether a number property is an Integer
or a Float
? Or discern between some of the temporal/date types? Let’s see how we can do that!
Examples with real data
To test all of these queries, I’m going to use a graph based on the Northwind data set that you can load by creating a free Neo4j Aura database and copying/pasting and then executing the entire load script available on Github.
Cypher functions
I’ve always used and relied upon the APOC utility library for many of my Cypher needs, and this is no exception. However, Cypher adds new functions and features, and some APOC features aren’t available in all cases (sad face for Aura), so I often dig through the Cypher functions first to see what’s available.
Although Cypher can’t help us get our answer this time, there are a few Cypher functions that look deceiving. The type()
and valueType()
functions look like they should return data types of a property, but they do not.
The type()
function returns a string representation of a relationship type, so instead of a Relationship data type, you get the text name of the relationship. The valueType()
function evaluates an expression and returns a string representation of its most precise value type.
Let’s look at some examples.
//type() function
MATCH (p:Product)<-[r:ORDERS]-(o:Order)
RETURN type(r) LIMIT 1
So, this could be helpful if you need to print out the relationship type or use it as a dynamic value for setting other relationships, but it’s not what we’re looking for.
//valueType() function
MATCH (p:Product {productName: "Teatime Chocolate Biscuits"})
RETURN valueType(p.productName)
This one is even more confusing at first. It evaluates an expression and returns the data type plus null status of the value. So, if you have a property that is a non-null Integer
, it will return INTEGER NOT NULL
. This might work (though a little over-engineered) if you want to get a single property’s data type, but it doesn’t work to get all the properties in a node because passing a whole node returns the complex data type NODE NOT NULL
.
These Cypher options might be similar, but are more complex than the basic feature we need. APOC to the rescue!
Options with APOC
The apoc.meta.cypher.type
function is the key to getting the data type of a property. It’s sister function apoc.meta.cypher.types
will return data types for all properties. Both functions return the property type(s) in string format. The functions take a single argument, which is the property/node you want to check.
//single property
MATCH (p:Product {productName: "Teatime Chocolate Biscuits"})
RETURN apoc.meta.cypher.type(p.productName);
//multiple properties
MATCH (p:Product {productName: "Teatime Chocolate Biscuits"})
RETURN apoc.meta.cypher.types(p);
Note that both of these functions can also handle a list as input, so we could pass in several Product nodes, and it would return the property types for each of them (example queries below). For this post, I chose to have the functions operate on a single entity just to keep the output cleaner.
//single property, multiple nodes
MATCH (p:Product)
RETURN apoc.meta.cypher.type(p.productName);
//multiple properties, multiple nodes
MATCH (p:Product)
RETURN apoc.meta.cypher.types(p);
Wrapping Up!
In today’s post, we figured out how to find the data types of properties in Neo4j. We looked at the Cypher functions type()
and valueType()
, which are close to what we need, but not quite. We then turned to the APOC library and found the apoc.meta.cypher.type
and apoc.meta.cypher.types
functions, which provide exactly what we were looking for.
I hope this post helps you out the next time you need to find the data type of a property in Neo4j. Happy coding!
Resources
Documentation: Cypher Values and Types
Documentation: Neo4j Java: Values and Types
Documentation:
apoc.meta.cypher.type
functionDocumentation:
apoc.meta.cypher.types
function