Thinking in Relationships: Practical Graph Database Modelling in Java with Neo4j by Paulien van Alst
About this talk
This talk explores the modeling of relationships and entities within a graph database context, specifically for Spring Boot applications utilizing Neo4j. The speaker, a consultant and Java/Kotlin developer, emphasizes the significance of data relationships, moving beyond traditional relational databases to graph solutions. Key concepts discussed include nodes, relationships, properties, and the importance of using the Cypher query language for pattern matching in graph databases. Additionally, the speaker provides practical insights into data modeling and its impact on querying performance, stressing the need for thorough planning and collaboration among team members before implementing a solution. Various use cases for graph databases are highlighted, including family trees, social networks, and recipe management systems.
Full transcript
[music] >> Good morning everyone. Today we're going to think about relationships and the entities that they connect together and how to model them into a graph database for Spring Boot applications that are using Neo4j. So, we all were live in this world where data is highly interconnected. But imagine that the data that you're working with simply does not live in the tables that you used to plot
your data in. And the reason why they don't plot that easily into those data tables actually uh matters to the business. You're working with data that you try to store into tables and somehow you need to relate it to one another and you always end up with this coupling table where crucial information about your domain is stored and it's quite hard to get it out there with
simple queries. When we as developers are thinking about storing data or at least I am thinking about it, I immediately think of relational databases by the means of PostgreSQL, MySQL, or Oracle. Those are my go-to options if I want to store data without even thinking. But sometimes those solutions are either too strict or too expensive or there are many reasons why you don't really want to go
to it. Then you can also think of no SQL databases. Think of MongoDB as a document store or Redis as a key-value store. Cassandra for wide column storage. But if you think of graph databases, my first hit when I'm looking for options would be Neo4j. Just be aware that this is not a product pitch for Neo4j. I'm not working for Neo4j. It's the only graph database that
I used to work with. So that's why I'm talking about Neo4j today. Who am I? I'm Pauline van Oost. I'm a Java developer, Kotlin developer at OpenValue. I'm a consultant and working for companies that are facing innovation challenges. I'm also a co-organizer of the Java User Group Noord in the Netherlands. It's up north of the Netherlands and I live there together with my boyfriend, two kids, a
dog. We try to rebuild our home and maintain a huge garden. Somehow I have some time left to come here and speak. So let's forget about relational and plot our minds to graph databases. Graph databases can be described with first-class citizens that are nodes, relationships, and properties. In other in some articles you might find the terms vertices for nodes and edges for relationship. Most of the times
those are more than mathematical articles. I won't be using those terms because I've always been taught with nodes and relationships. So that's why I'm talking about nodes and relationships in this talk. Properties are also first-class citizens in graph databases as they add valuable metadata to your graph. A graph can be for example something like this where you have several nodes, each color describing the kind of node
that you can see here. In blue, an author. In purple, recipes. And in orange, a keyword that can relate to those recipes. And as you can see here, not only the nodes have types but also the relationship do have types. For instance, the relationship between an author and a recipe is typed by the key by the word wrote pesto relating to a tomato mozzarella recipe by the
type keyword. This already indicates that relationship are storing valuable information regarding your domain, valuable functional information about your domain. Query languages you will use on graph databases highly rely on pattern matching, which in my regard is very valuable because it's a very visual um language a query language. This is just a one example that could show a graph like you're shown here. You can see here that
it's highly descriptive and matching the graph that you are seeing. Some common use cases to use graph databases, obviously, very valuable for domains where data is highly connected. Entities should not stand on their own on a graph. Mathematically, a dangling node could represent a graph. But is that a useful graph? Just one node with no relationships? Well, no, it's not. that's not only thing relationships are are
own part of the domain as well. They hold very valuable information of that domain. Some concrete examples are of those data sets are obviously a family tree. If you're thinking of a graph in your mind, your first go-to option would be a family tree where family members are linked to each other with different kind of relationships. Also social networks. Think of a school structure describing students and
um classes, um courses that can be followed whatsoever. Or HR administration relating employees to their managers or departments and positions. Another very common example could be investigations of Panama Papers where data analysts or researchers could identify communities in those Panama Papers by investigating the data that is in there through a graph database. The strengths of a data of a graph database is again the relationships directly in
the model. I've stated that already a few times. You don't need to write down very complex join query to find out all the data that is related to one another. Although you can. So if you love those queries, you can still write them, no worries. You are not obliged to a tight schema to model your data into. But no worries. It doesn't mean that you can do
anything on the graph that you are working on. You can still set some rules and set some structure in. No schema doesn't mean entire freedom. Because you can still query your you can still tune your queries by using indexes or imposing constraints on the data that get inserted in the database. So you can still make sure that the graphs that are inserted in a certain is compliant
to some of those rules. And which is also pretty valuable is that you can have advanced analytic tooling into a graph database right ahead. You don't need to figure it out all by yourself. Now as I said, today we're going to talk about one particular graph database which is represented by Neo4j. So what about Neo4j? Neo4j is a pretty mature database I would say. Um it guarantees
asset transactions. It connects with the Bolt protocol which is carried over TCP or web sockets and this ensures that your queries are properly executed from your application um to your database. It uses Cypher as a query language and it has Neo4j Desktop as a viewer on your database, which can be viewed as DB um >> [clears throat] >> Yeah, which is your database viewer, sorry. Cypher is
its query language and it's pretty declarative. It's close to the natural language, designed to graphically match the graph, and it's highly highly highly relying on pattern matching. Those few bullet points I put them there separately because I find them very valuable and in my experience um it helps out to write out your queries and actually discuss them with your business owner, business analyst, or anyone that has
functional knowledge of Because language is so graphical and a bit less um relying on highly um uh Boolean logic, it's it's easier to just level with people with functional domain knowledge. It's also come along with uh a library, the APOC library, which stands for awesome procedure on Cypher, which has a lot of procedures and functions that can help you out with many type of things. Like collection
manipulations or graph algorithms. Or here they're stating also data conversion, but there are very a lot of functions already in there. They're not there by default. As you can see, this is a screenshot from the Neo4j Desktop application where you can install local instances. You need to install it by yourself, either if it's locally on your laptop or if you're deploying into a cloud environment or in
your Docker image. But it is there also in the community editions. So let's discover a graph because today we're going to do some data modeling and before doing some data modeling, I want you to see how it is to query a graph and to the get into your head how you would look at such a graph. So that means that I'm now going to the this Neo4j
Desktop which is a product that you can just uh download and install your local machine. And in that local machine, you can install and select everything. Just some instances to play around with. You can even install some graphs if you want just to play around and to discover how it is to be to to to work on a graph. I would actually recommend to do that before
you start working on a project with Neo4j. There are a lot of graphs out there that you can write in certain locally either on the Neo4j website on Kaggle or other data platforms. A nice feature I think of Neo4j as well is that in an instance you can actually maintain several databases which can be nice if you want to discover or several domains or play around with
several graphs into your applications. You only need to deploy one instance. As you can see as well over here you can connect to it using that particular bolt protocol which always will expose this type of port. And if you want now to discover what's in there, you can just connect to that graph and start querying. Now if I want to start querying on my I can do
so by starting with the keyword match. Match is a keyword that you will always use to try to find something into Now I want to start querying just one single note which is of a type utensil in this example that I thought of. To declare a type, I need to use a pre-leading semicolon to make sure to indicate to the query this is the type I want
to look for. And then I want to return that particular note. I will do so by assigning a variable to that note which is in this in this case just a letter U. This query will actually return all the notes that are matching that are matching this this type. In this particular graph, there are only three of them. If I only want only want to return one
I can just limit it with the keyword So those queries are not that different from SQL but a bit more descriptive using those curly brackets. If I now want to go and find out a more particular entity for instance one that is matching this name I can actually start to use those properties that are declared on the note by just opening curly brackets and then using a
dictionary to describe the property the note with a certain property I'm looking for. And that will exactly find the same note over again. You can do the same if you don't really like the syntax, you can approach it a bit more with a SQL like instance where you can say I want the name of my note to be equal to this certain field I just copied. So
then you're finding you're finding back the semantics of a SQL database. Both are valid and both are doing the same thing. The query planner will exactly execute the same thing. But we are here not to find single entities as I said it's not very useful. We also here to find relationships. So now let's see if I can see query a note that is related Let's Let's say
a recipe. I want to see this whole relationship, this whole path. So I will actually assign values to both the note, the relationship and the target note. And make sure that this is returned. I need to put some commas over here otherwise it won't return it. And then I will actually retrieve it right away. I would like it to show it a bit better. Here you can
see the whole path that I was querying for. talking about paths actually you can also describe it as a path by assigning to a value P and then return it in the same manner. Now this is just one path, one note relating to one other note. I can also say that I want for instance because I know this is the case in this graph that I want
to find an author that is related to ingredients using a path with any type of length. Then you're using the asterisks and that will return all the paths that are relating an author to an ingredient no matter how many hops it needs to take in the graph. And this will actually return the whole graph that I stored in this database because I said you could the authors
are my top notes in this graph and and my ingredients are my leaf notes and it's returning all the paths between those top and leaf notes. So those are some very basic understandings of querying. I forgot just one is that I can also specify a type of relationship, I can actually specify it again by using a semicolon into my relationship just to return that path. This will
actually return all the authors related to some kind of recipes. Actually, you will see that some this is not Yeah. This relationship also has properties. So this again you can actually look out for um properties like I did for notes, you can also do that for relationships. This should work as well. These are all the relationships all the recipes that have been published on a website for
instance. So very small introduction into Cypher. There are much more features that you can look into but that will mean that I will go way over time if I introduce that to you all. Just get it into your back of your head because now we're going to start to do some data modeling. Because Neo4j will now be used actually to express our domain. We are going to
do some data modeling. And why I wanted to give this talk is because on several assignments that I worked on, I discovered that the investment of time prior to implementing a solution with was very too short at the end. Or the the the time they invest to model the data was too short. And they ended up with a solution that they actually didn't really like and they
blamed the tool. It was actually making or breaking their experience while it's really important to invest some amount of time, some significant amount of time before starting your experience. And by experience I mean going to production. When you're going to start your data modeling, it's important to involve everyone. Both your business owners, testers, developers, architects and whoever has any knowledge or something to say about your domain
should be involved in the discussion about how you guys are going to model your data into a graph solution. Just because there are plenty solutions plenty of graph solutions that will fit but there will be only a few that will actually fit your challenges. If you are start to model your data, you will start by just drawing your main item entities. If you're going to model a
recipe inventory two entities will come ahead straight into your head at first. Recipes and ingredients, that's the most obvious one part. What's good to do then is to start how could connect to each other. They can from recipe to ingredient but obviously they can also connect starting an ingredient to a recipe. And what important to do next when you are trying to model the data that you're
working with is to write down the questions you want to ask to the domain. Because in this particular example if you're looking for the ingredients that are needed in a recipe, that's one question that your application will ask for, then it's obvious that you will want to model the relationship starting from the recipe going to the ingredient because the entry point of the querying answering this question
will be the recipe and then you're going downwards if your application will be more focused finding ingredients finding recipes that are related to recipes, then you will actually want to relationships other way around. This actually really matters on the for on the reading performance and also on the your understanding of the domain you're working with. If you do don't if you don't do this correctly, you might
end up with queries that are really poorly performing and then you will think that Neo4j is not really good at reading which actually is. Test those questions then again against the the the entities and relationships that you have drawn in step one and two. And that is actually your plan of attack when you start modeling. You start to draw your main entities. You start how to to
draw how to connect to each other. You write down your questions you want to ask to your domain. And you test those questions to see if you can answer them. You evaluate how that went. And if that went easy, because if it's hard to write out the uh that will represent the response, it's probably hard to write down the query as well. And then you start over
again until you have no awkward solutions anymore. Um yeah. [sighs] Because you will have while doing this exercise on our um more industry uh challenge, you will see that this will uh take quite some iterations. At one of my clients, we spent actually 2 days remodel a graph, remodel a solution. One of the challenges that we had was to forget about the graph that we already had
running in production. That took us half a day. And then uh we finally ended up um together with a consultant of Neo4j actually uh with a graph that was very much more performing. By investing those 2 days, we managed to get uh rid of uh caching mechanism implemented in Redis. And we could directly just um uh query our application uh to Neo4j without using any other caching
and the caching of the database. So, modeling a good graph is very, very important. And it's really valuable of your time. But don't take months either. Don't overdo it either. But it's important just to do this exercise. And again, I don't know if it's very visible on this slide, but the drawing part here is very important. Forget about the queries. Forget about uh coding. Just start drawing
because the the power of graphs is actually that this visuali- visualization part is so strong. So, as as you might notice, today we're thinking of recipes and ingredients. And um this was just one very uh And we are going to model it ourselves. Let's start off with this first solution that we draw it until now, where we have recipes and ingredients connected to And let's think of
a very, very simple recipe inventory of a sandwich place. Then on my whiteboard, I will start drawing three ingredients. Why three? Because most of the time, I will have more than two ingredients into a recipe. So, I just draw one more on my whiteboard. I also draw my recipe This is the most intuitive solution of a graph that I could think of. The most intuitive relationship is
as I can just call this relationship that an ingredient is used in a recipe. Make sure that when you're drawing those relationship, you don't use very generic types for your relationship. Relates to, is part of, is child of. Because those are very too generic and fitting to each and every domain that I can think of. But what you want to do is to find terms that are
really suiting your domain and expressing a sentence. This is fine. Used in this way to generic, but let's This is the starting point of my data modeling. If I then want to describe how a tuna sandwich would look like, very simple tuna sandwich so to say, this could be it. I I want to put some salad. I want to use some salad in it, some tuna spread,
and some bread. This could be fine for a very small sandwich store that you will find here in the city. But as that sandwich store is expanding and becoming a way more international sandwich store that I can find back in Amsterdam in the Netherlands, the amount of recipes growing along. And then we can end up in one bottleneck of this graph. Is that we might end up
with this kind of solution with two highly connected nodes. Because a lot of the sandwiches we eat nowadays, this went too fast, they have some salad and they have some bread. So, if I'm going to a graph that is um representing a million of recipes, all holding bread and salad, those nodes are being highly connected to each and every recipe. And they become uh a bottleneck into
your into querying. But this graph would still hold for a very small business. So, it's a good graph in a way that it's simple to insert, is descriptive, is easy for simple questions. And the cons is that it's a monotone graph um when your data is growing. And then your solution is not fitting your business anymore. So, another thing that you could say, instead of having simple
ingredients, you could say I have vegetables, I have spreads, and I have all kind of breads. I've now become a more elaborate sandwich company. And I still have recipes because recipes was fine. And now you can think of that maybe I want to insert other kind of relationship into um into my graph. I want to say how vegetables can be put on a spread for Or how
the spread how the spread is put on the bread. I can still find out another name for the relationship to the recipe. It's good to change those name those obvious names towards your iterations of designing a And now I've got a much more information Because actually the bottom row is describing the recipe and the steps I should follow just to uh to create that sandwich. So, this
graph is already telling me more about the domain than my previous But imagine I want to request something about ingredients. That was not possible when I was calling them vegetables, spread, and bread. But fortunately in Neo4j, you can actually add a secondary label to your which can then gather all those nodes back again into one type. Then you can choose when you're querying whether you want to
target only the vegetable nodes or the ingredient nodes. For your query planner, that can matter and that can actually help you out with some of your queries. So, if I'm now going back to my tuna sandwich example, you will see um that the whole recipe is written down. So, then again, this is another graph that could be fitting my solution of a sandwich store. The pros of
this example is that the recipe can be read from the graph. Ingredients have all their own type. The cons is that it can be too specific or too complicated to proceed with the business application. And maybe it's also very hard to define when something is a subgroup or not. For bread, maybe it was very obvious, but for the spreads, maybe not. Or there are other challenges. So,
be aware that if you're making nodes more specific, that you can maybe make them too specific. So, there balance to take there. And make sure that you don't have many, many relationship between ingredients for instance. We're saying uh salad is uh topping of the the spread, but then you need to add some information in what which recipe that's the case and so on. And then it becomes
a bit more too complicated. So, that's a balance that you can take. These were two examples on how you can uh model um this this challenge. What you want to look out for during uh your data modeling is to look out for extremely highly connected nodes. It's very easy to start small. You should start small. But as as your graph is expanding, uh highly connected nodes or
dense nodes or whatever you might call them, can form a bottleneck into querying for the data planner. The for the query planner, you must imagine that sometimes the query planner need to discover the whole graph to find out some paths. Even if there's a one highly connected node, it will always go through that node, which is highly extensive. expensive. The direction of the relationship matters. The query
planner will always go uh from top to bottom. So, it's also important to keep into your mind. Define your indexes wisely. I won't elaborate on that because that's a separate talk. Um but keep in mind that graph databases do use them. And it's a mature database. So, that means that you can always use an explain plan and a profile before running your query on your production data
set, which you should actually do. Some tips to solve all your challenges when you're doing your data modeling, try to make them as specific as they are fitting the data the the the your domain, your functional domain. Change the node type until you have this less awkward name. The same goes for relationship. um very connected nodes are um are popping up into your domain, you can also
try to categorize them using properties. That can also be um a solution. As properties are also first-class citizens in your graph. And always challenge the business requirement. Is it really necessary sary right away? Can we postpone this kind of query? Can we maybe discover a bit more about this domain? Um and always ask which are the most frequent queries, which one will be um involving a lot
of data, which one are not. Another thing that you should be aware in a graph is the path traversal. A few model graph that looks functionally correct. For instance, this one is to is a graph modeling how you can build up a pizza. But then your business will always want to require which one always want to ask which kind of cheese will be on the Which is
a leaf note in this example. Then the database always need to go to that leaf note to just check if the path to the condition you're meeting up. That's very expensive as well. One way to solve this is to maybe put one direct relationship between your top note and your leaf note. But that's something you should think of if that's valuable one. But leaf notes um are
really expensive to query. So, that's important to keep in the back of your mind. Now, this this was a bit about the data And now let's see how this can be put in practice into application. The application that we are going to see, you already saw a bit when we were querying with Cypher. It's a data set recipes that are written by authors. Each recipe needs ingredients
and are composed of steps. And of course they require the use of utensils. The questions that you could ask to such a graph is that you want to look up You want to list the most used ingredients, list all the recipes and group them by authors for instance. which authors are making the most diverse recipes using the most ingredients per recipe. The graph of the domain that
of the application that I'm going to show you is that an author can thereby write a recipe. A recipe requires ingredients, but sometimes you also have optional um ingredients. So, this shows again that you can even write down two different kind of relationship between two A recipe is prepared by steps. And utensils are used in recipes. Our text stack, it's a Spring Boot application written down in
Kotlin using Spring Data to do the connection with your Neo4j graph. And I deployed my Neo4j graph locally on my laptop, but you can deploy it anywhere you want. let's show you some code now. And I hope this can be seen from the back because otherwise I will increase the font a bit. will easily integrate with your your Spring Boot application as you have a Spring Boot
starter. Which means you can auto use auto configuration just to configure the connection with your database stating the Neo4j, your authentication, and my highly secret password. even if a good thing to remember when you're working with is that you can always set the logging to debug if you want to monitor the queries that are being generated. If I now want to put my graph model Spring Boot
application, I can describe it by using entities. As I said, there is no schema imposed in Neo4j. But the application that I'm now going to describe actually has a schema. However, if my application is not going to find any nodes compliant to the schema described here, it will just return nothing. So, nothing will break. If I want to describe a node in in my Spring Boot application,
I can just write down a class or a record in Java annotated with node. Of course, my entities are still entities. So, they should have an ID with a generated value. And that node in this case is related to recipes. However, what you would see here is that I don't have a list of recipes, but I have a list of Those relationships are targeted with an annotation.
Um which declares the type of my relationship and the direction. It can be outgoing or incoming. the list that I have here is of the type of the relationship. It has the name has written and it describes all the relations properties. So, also the properties that I can put into my And this is the place where we'll see the target note of that relationship. That is listed
here. And then the recipe actually is modeled in the same regard. This one is a bit more complicated. It has different kind and some kind of uh properties. Important to notice is that you can also insert durations in A duration is just a type in Neo4j, which actually also maps a pretty fluently between Java and the Neo4j Now, if I want to query the data in um
in my in my application, I can just declare Spring Data uh repositories. There are uh Neo4j repositories already there. You declare them as you would declare a DBC repository. This one is as actually mapping authors. Uh which have an ID of type long. I can declare custom generated queries by just write them out with the Spring Data mechanism. So, this one is finding a name containing a
part of a name. So, I can do some um some text search in Neo4j as well. and but I can also write out my own queries. So, this one is just a Cypher query that I could also have written into my Neo4j desktop. If I don't want to retrieve um any entities or a node or relationship, but I just want to um find something else like I
had to find it. But some kind of statistics, I can make use of projections. Projections are just a represent another representation of the data that you're retrieving. In this way in this query, I'm actually retrieving all the ingredients and how many times there are occurring into a recipe using the count function. I'm using this projection most used ingredient row that only holds holds two fields. And then
the mapper will automatically fill in my my bean. If I'm now going to my API, I can see how those queries are evaluated. Let me see. I need to start it over. let's see. >> [snorts] >> Oh, here it is. Can actually connecting right away with my Neo4j database. Here you can see it. It has connected to it. And it's logging a lot about all the all
the nodes that it has detected. If I'm going to my browser where I've actually stored my my Swagger UI, here I have some recipes. I will just make it a bit bigger. And I can actually start to um request rec um recipes that are for instance containing the letters m a d in this particular order. Oh, it's Oh, yeah, it's case-sensitive. And hereby I can retrieve a
recipe which is actually called madelines and not m a And you will see that now the Spring Data has generated a query that I have not written down. It's a recipe that contains uh that has a name that contains the value that I have given or the description that contains something that I have given. And that was actually the that was generated with with this one. >>
[laughter] >> This one I have written out, but for ingredients is actually the one that um Spring Data has generated. So, let's Here I have it. Here I have flour. I have several types of flour into my domain. And if I go back to my logging, you will see that now it has generated Here it is. This is the query that Spring Data has generated for me.
And this is the function that was corresponding to it. You can also use the methods that you will usually find like if I want to find all the recipes, I can just say here. Uh this is my endpoint actually. This will find all the recipes. I did some mapping not to show all the properties of the node. And if I go then into my logging, you will
see that here it was matching all the recipes and returning them. And if I go to my endpoints and look out for my get all recipes and go to my surface that is actually calling the find all solution that Spring Data will propose to lots of those Spring Data repositories. So that's also neatly integrating with I will go back to my presentation now. So that was a
bit of the coding. My lessons learned again from the project I've worked on is do not try to model ball >> too many of the possible future requirements ahead. Start to try to stick to the requirements you are facing Embrace the flexibility of the graph database has to offer because you're not strictly tied or married to the graph database you're Use the constraints and indexes that you
can declare on and think of your architecture. What about the future actually but we still because you still want to get this in the back of your head. When you don't know about it but you can still make sure that you have a good ETL process in place to be able to remodel at any time your graph. And there you will find back the relational database where
you don't store your relations already but just store your data as flat as possible. Have some awesome process that will actually then insert it into your graph database to enable you to have some flexibility to change solutions because it's really really really challenging sometimes. But it's really nice to work with so. So I hope this short introduction has inspired you to maybe play around a bit and
uh help you out with your challenges. Thank for attending this talk. [applause] And I'm curious to see if there are any questions asked. Um does you mean if you want to version your graph? Yeah. You can insert as many graphs as what you can do with this is a very hard challenge ahead. We asked it to the Neo4j consultant that we had over. And they didn't found
a solution yet to implement it right away. Um you can start introducing a top note which helps version. It's always one note that you will start from so it's not really expensive. Or you can set it into the properties. Hard challenge. We didn't found a proper solution to manage versions of the graph to be honest. We actually asked business not to put that into a business requirement.
Yeah. I'm sorry for this response. Are there any questions? Yes. Or like? Yeah, Neptune or you have TigerGraph or they are more yeah. Um I don't have any views. I've read into them but I've no production experience on it so I can't say anything about it. Yeah. no. It's never by directional. It's also it always having one direction but in your query you don't have to specify
the So you can actually write down a unidirectional relationship without those thingies just two dashes. Um but then you're giving less information to your query planner so obviously the query will be less performant. Yeah. This depends on the questions you're going to ask to your data. Are you really going to query into the relationships? Does it matter um Are you going to do some analytics on it
as well? Are you going to do community detection for instance which is really a graph feature or are you going to do some path traversal? Those are really properties. So then a graph becomes a more of a good solution to go for. MongoDB would be Let me see again. The the most valuable thing is that you can request everything about those relationship and all the paths that
you're going to to to traverse to. One of the clients I've worked with was building a navigation tree, flexible navigation tree depending on the customer that was going to request. So this it was a tree. So then it's obvious that you're going to go for a graph solution. So yeah. It's it's it really depends on what you're going to ask to the to the data. Yeah, that's
fine. That's all fine. Mhm. Yeah, there are some graph fronted libraries that you can use to visualize your graph database. I'm now forgetting about which libraries you can use them but so you have to look them up. Um but we at another client we actually implemented the whole front end so investigators could query throughout the graph to discover patterns in the data. So that's entirely possible. You
don't need to give them right away access. No. No, please don't because they have no query experience. Yeah. No no but I can understand your question because the the Neo4j desktop is already really intuitive and feeling like a UI. So your business users when they discover your query on this they will request access. Yeah, so don't give them that. Give them a front end where you're already
pre-filtering the data they're exposed to and let them just click it through. But there are some some some libraries that you can use to represent the data. Yeah, the probably is going is used in Neo4j desktop as well. Still a question? Yeah. Yeah, indexes can help with that. There are various ways to define indexes either on your relationships, on your notes, on the properties they're holding on.
You need to define them wisely. The same rules applies as to a relational database so don't index all your graph. Only index the fields that you will be querying on. Um unique constraints will automatically generate an index as well so those are all the rules that you can follow to tune your Please remember that a Neo4j database also have a caching layer. So some queries will just
maybe warm up your cache as well. Uh I don't know if you can forbid relationships to be honest. I have but maybe you are but you can create relationships that are pointing to the same identity identity back. Yes. No. I'm I have to look that up or you can look that up into the documentation. The documentation of Neo4j is very elaborate. But yeah, you can define circular
dependencies for sure. Yeah. If no rules applies. Any other questions, Peter? No, it's not I don't know. No, not for sure. No, it's not because it's graph is in the name then no. No, I'm sorry. I don't know actually. To be honest, I don't know but that's not an obvious connection to me. Any other questions? Yes. Mhm. Yeah. I have never faced problems with typing. No, in
Neo4j it's been written in Java I think it is pretty strongly typed. Um you can use a lot of types to define your properties and so on. Especially the duration is really nicely mapped from Neo4j to the Java beans. Um so I haven't encountered any problems with that. no. No, for sure. Last question cuz I'm a bit over time. Yes, sir. Fuzzy matching, yes. There is. You
can do fuzzy matching in Neo4j. It It has a lot of techniques to do that. And you can look that up as well. It's very well it's using Lucene indexes as well under the hood, so yeah. That was it. Thank you all for attending. >> [applause]
More from this event
See all 38 talks →
Spring I/O 2026 Keynote
1:08:44
The Spring AI Ecosystem in 2026: From Foundations to Agents @ Spring I/O 2026
43:39
Breaching LLM-Powered Applications: Overcoming Security and Privacy Challenges by Brian Vermeer
48:40
New in Spring Security 7: MFA, OAuth2 and more by Daniel Garnier @ Spring I/O 2026
46:43