In this workshop we will build and deploy a full stack GraphQL application using Next.js, Neo4j, and Vercel. Using a knowledge graph of news articles we will first build a GraphQL API using Next.js API routes and the Neo4j GraphQL Library. Next, we focus on the front-end, exploring how to use GraphQL for data fetching with a Next.js application. Lastly, we explore how to add personalization and content recommendation in our GraphQL API to serve relevant articles to our users, then deploy our application to the cloud using Vercel and Neo4j Aura.
Table of contents:
- Next.js overview and getting started with Next.js
- API Routes with Next.js & building a GraphQL API
- Using the Neo4j GraphQL Library
- Working with Apollo Client and GraphQL data fetching in Next.js
- Deploying with Vercel and Neo4j Aura
Full Stack GraphQL In The Cloud With Neo4j Aura, Next.js, & Vercel
In this workshop we will build and deploy a full stack GraphQL application using Next.js, Neo4j, and Vercel. Using a knowledge graph of news articles we will first build a GraphQL API using Next.js API routes and the Neo4j GraphQL Library. Next, we focus on the front-end, exploring how to use GraphQL for data fetching with a Next.js application. Lastly, we explore how to add personalization and content recommendation in our GraphQL API to serve relevant articles to our users, then deploy our application to the cloud using Vercel and Neo4j Aura.
AI Generated Video Summary
The Workshop covered various topics related to building a full stack news article application using Neo4j AuraDB, GraphQL, and Next.js. It discussed graph data models, traversing graphs, and building GraphQL APIs backed by Neo4j. The Neo4j GraphQL library was highlighted for its ability to generate resolver functions and optimize database queries. The Workshop also covered Next.js and deploying the application to Vercel. Custom logic was added to the GraphQL API using the Cypher-GraphQL-Schema directive.
1. Getting Started with Neo4j AuraDB
In this part, we will get started with Neo4j AuraDB and build a full stack news article application using GraphQL and Next.js. We will cover how to handle data fetching with GraphQL in a React app and specifically with Next.js. We'll start off in Neo4j Aura, import some data on news articles, and use the query language Cypher to work with the data. Then, we'll build GraphQL APIs backed by Neo4j using the Neo4j GraphQL library. Finally, we'll run our GraphQL server in Next.js and deploy the application to Vercel.
So, make it simple, and learn things about Graph technology. So, here's kind of the rough outline for today. So, the goal of today is to build a full stack application, including building the GraphQL server, working with the database, building a Next.js React application that queries our GraphQL API, and then we're going to deploy that to the cloud with Versal. So, we'll be using a Neo4j AuraDB, as we said that Neo4j is a Graph database, Neo4j Aura and AuraDB is like a hosted Neo4j in the cloud, so it allows us to spin up Neo4j instances in the cloud that are private to us. We're gonna use the free tier of Neo4j Aura, so we don't need to have a credit card or incur any fees or anything like that. We will be using GitHub, so you should have a GitHub account. And then we'll be using Vercell to deploy our application. Vercell also has a free tier, so we just need to create a Vercell account.
So, we're gonna start off talking about Neo4j and getting started with Neo4j AuraDB. So, we're going to work with some data about news articles. We're gonna build a full stack news article application using GraphQL and Next.js. We're not gonna focus so much on front end design, we're mostly gonna focus on how the pieces fit together. But we will, we will cover how to handle data fetching with GraphQL in a React app and specifically with Next.js. Cool, so that's, yeah, that's kind of the order we're gonna go in, starting with Neo4j. We'll start off in Neo4j Aura, we'll import some data on news articles, we'll see how to use a query language called Cypher to work with the data, including things like, can we recommend similar articles, the sort of thing, recommendation personalization queries. Then we're going to see how to build GraphQL APIs backed by Neo4j, so we're gonna build a GraphQL API using the Neo4j GraphQL library, which is a Node.js library. We will see how to actually run our GraphQL server in Next.js, so for Next.js, we're gonna use Next.js both for the backend, the API routes functionality, and then also for the front-end React application. Then we will deploy our application to Vercel, so both the front-end React app and our GraphQL API will be deployed as server-less functions.
2. Deploying to Vercel and Introduction to Neo4j
We will deploy our application to Vercel and make it interactive and hands-on. We'll have hands-on exercise segments and provide starting code. Let's talk about Neo4j and Neo4j Aura DB. The workshop is scheduled for three hours, and we'll see how it goes.
Then we will deploy our application to Vercel, so both the front-end React app and our GraphQL API will be deployed as server-less functions. Cool, so let's get started. I do want this to be as interactive and as hands-on as we can, so as we go through this, if you have questions and comments, drop it in the chat and I'll definitely address those as we move along. You'll also see this hands-on exercise icon, so definitely want this to be hands-on, so there will be, oh, I think we have five or six, so sort of hands-on exercise segments where we're gonna work through some exercises together as we build up our application.
Not gonna start from scratch, we'll have some starting code to help us along, but yeah, try to make this as hands-on as possible. So definitely ask questions in the chat, let us know how things are going. And when you see this hands-on exercise icon in the slides, that means we're gonna spend a few minutes working on something together.
Great. So to get started, let's talk a bit about Neo4j and Neo4j Ora DB. I guess we should also talk about the time here. So this is scheduled I think as a three-hour workshop. We haven't done this one before. This is kind of new. So we will play it by ear. I think three hours will probably be good, but we certainly won't go over. Not sure if we'll finish early.
3. Continuity and Introduction to Neo4j Aura
In this part, we discuss the continuity of the training session from the previous week and introduce Neo4j Aura as a graph database. We explain the concept of graphs and nodes, as well as the use of the query language Cypher. We also mention the use of Neo4j in real-world use cases, such as investigating offshore corporations. Finally, we provide instructions for signing up for Neo4j Aura and creating a new Aura DB instance.
So a question from Mohammed in the chat, is this training session continuous to the previous one? Yeah, good question. So was that last week? Yeah, last week I did a workshop focused on building GraphQL APIs with the Neo4j GraphQL library. So if you took that session, there'll be some similar concepts that will transfer. In that workshop we spent sort of three hours going deep on the features of just using the Neo4j GraphQL library to build a GraphQL API. And we just kind of left it that we didn't really see like how does that fit into the context of deploying our application, a front end application, how do we use cloud services with that. So today, the focus is really on how these different pieces fit together for building a full stack application. So, we're going to use a different data set and in that one last week we built a GraphQL API for an online bookstore. Today we're focusing on a different data set with real world data of news articles in a graph. So if you took the workshop last week, most of this will be new, there'll be again, a little bit of overlap in the concepts. But I think it should be worthwhile. Hopefully that that answers your question. Cool.
So let's talk about Neo4j Aura. So first of all, what is Neo4j? Well, we said that the graph database, you may be familiar with like relational databases or document databases, where in a relational database, the data model that we're working with is tables. In a document database, we have collections of documents like JSON documents. In a graph database, we have graphs that we work with. So in a graph nodes, these are the entities, relationships, connect them and we can store sort of arbitrary key-value pair properties on nodes or relationships. Those are the attributes. In Neo4j, we use a query language called cipher to work with the data, both for creating and querying the data. So if you're familiar with SQL or you've heard of SQL, you can think of cipher as kind of like SQL, but designed for graphs. So in this example, on the upper right here, that is a cipher query that is searching for addresses in New York, and then looking for people connected to offshore companies in New York. This query comes from the Panama Papers or Pandora Papers datasets that is an investigative journalist's datasets looking at offshore corporations. The group that did that investigation used Neo4j to make sense of very nested structured data of offshore corporations and people connected to them. So I think that's a good example and kind of ties things to a real world use case, but there are lots of interesting things we can do with graphs and with graph databases. We're gonna focus on more of the I'm building an application kind of like operational transactional use cases. But there are lots of interesting things as well that we can do with graph analytics like graph algorithms, graph data science or data visualization as a graph but we'll be using the graphical integration for helping to build that API layer today. So really I think of Neo4j as kind of the core piece of this graph platform where the database gives us the ability to model, store, query our data as a graph, and then there's lots of tooling and different integrations depending on what we're working on. So on kind of the right side of the spectrum is more of the analytics, data science things where I'm interested in things like graph data science, graph algorithms, graph visualization, and then what we're focusing on today is more on the left side where we're more interested in operational, transactional use cases. I wanna build an API layer for my news application or I wanna build the API layer for a e-commerce site, things like this.
So, okay, great, here's our first hands-on exercise of the day. We are all going to sign in to Neo4j Aura and create a new Aura DB instance that is private to ourselves. So let me drop the link to the Neo4j Aura in the chat. So, there's the link, I'll just drop the link in discord. So what we're gonna do is go to that link and sign in for Neo4j Aura and create a new Aura DB free instance. When you do that, you'll be presented with a random password. Be sure to copy that password, save it somewhere, so we'll use that pretty much immediately. This is kind of what the flow looks like, I'll go through this in a minute. Basically, once you sign in, you'll see this screen where you are prompted to create a database, either free or professional. We want the free tier for the workshop today, you'll give it a name, you can choose a region, I just usually select whatever region comes up first. There's a few different, you can also select whatever is closest to you. And then you have two options to start with an existing data set about movies or to start a blank database. And we wanna start with a blank database. This is where you'll see the password, this is randomly generated, you can change this later, but you do need to copy this, save it somewhere, because we'll use that in the next step when we go to start using Neo4j browser for writing queries. So you'll see in the Aura console, we're starting your database, so it'll take a couple of minutes to spin up. And then when you see this green running, then you'll see also this URI, this connection string for your Neo4j Aura instance. And we also will want to copy that, we'll use this later on for our GraphQL API to connect to our Neo4j Aura instance. So I'm gonna go do that now. So dev.neo4j.com slash neo4j dash Aura. And you can see that there's different tiers or a DB. We want the free tier. It's limited in the size of the data, but it's perfectly fine for like hobby projects or workshops like this. And you have a real-world application that you're ready to deploy. That's where the professional tier comes in or if you're a huge company enterprise and have lots of custom things. But okay, I'm going to sign in to Neo4j Aura. Oh, it looks like I was already signed in. When you sign in, you can sign in either with like GitHub or create an account via email if you haven't done that already. I'm going to click create a database or a DB free. Let's call this GraphQL Galaxy Workshop. And I'm just going to leave the region as Singapore. Sure, why not? Well, no, I will select one near me. Let's go with Iowa. Load or create your own data. So, I don't want the movie's dataset. I want to create my own data, so I'm going to select this one and we don't need to update that. Thank you. Okay, create database. So, here's my password. I'm going to copy that. Save it somewhere where I won't lose it. Say yes, yes I have.
4. Setting up Database and Introduction to Graphs
In this part, we will set up the database and give everyone a chance to create a Neo4j or a DB instance. If you encountered any issues, let us know in the chat. While waiting for the instance to spin up, we'll discuss graphs and the data sets we'll be working with today.
Save that, and here we'll see, okay, now we're setting up my database. It'll take a few minutes to do that. Cool, so when you get to this screen, you should be good for now. So, let's pause. I'll go back to this slide. And let's pause for just a couple of minutes to give everyone a chance to create a Neo4j or a DB instance. If you did the workshop from last week, you can use the same database. That's fine, or you can destroy that one and create a new one. It doesn't really matter. But yeah, let's pause just a couple of minutes and then we'll move on. If you get stuck with anything or have any issues, just give a shout in the chat. Oh, and you can see an instance spun up or at least get to the gray screen that says it is in the process of starting up. Basically, you want to see something like this. Cool, well let's move on. But if you had an error or if anything isn't working, definitely let us know in the chat and we'll get it figured out. But let's talk a little bit about graphs and the data sets that we're going to work with today while we're waiting for our Neo4j Ora instance to spin up.
5. Graph Data Models and Working with News Articles
We work with a graph data model called a property graph in Neo4j. It consists of nodes, relationships, and properties. The knowledge graph concept helps us put things in context by connecting nodes of different types. In GraphQL, we also work with a graph data model, and the property graph and GraphQL data models are very similar. Today, we'll be working with news article data from the New York Times API, which includes articles, topics, authors, and more. We'll use a separate GitHub repo with code for loading this data set and building GraphQL APIs.
So we said earlier that the data model that we work with in Neo4j is a graph. So nodes, these are the entities, relationships connect nodes. In Neo4j, we use a specific data model called a property graph or also sometimes called the labeled property graph. So in the property graph, we have labels, first of all that define like the type or grouping of a node. So in this case we have the label node on all of our nodes, which is not very helpful. And then our relationships have a type and direction. And then we can store arbitrary, key value pair properties. That's where the property and property graph comes from. You may have heard the term knowledge graph in the context of property graphs. And I think knowledge graphs are really interesting because they help us put things in context, it's kind of how I like to think about it. So we're talking about things. So these are the nodes or entities and we know what kinds of things they are. So in this example we have some data from New York times articles. So we have article nodes, we have the title and the URL stored as properties on those nodes. And then the articles are connected to topic nodes. So here's an article about the infrastructure bill in the US, it has the topic United States politics and government. That's connected with this has topic relationship. This article has multiple topics, also about the US economy. We can see other articles connected to the same topic. So this is the idea of a knowledge graph where we're working with things and we know the type of the things, you have an article, a topic, a person. And we know the context of the thing. So what other things our article is connected to. That's basically what a knowledge graph is. When Google announced their knowledge graph API in 2012, I think it was, they published this blog post called things not strings. Just talking about the idea of a knowledge graph, which I think is a really good summary of kind of what we're talking about when we talk about knowledge graphs. So those may be some terms that you've heard in the context of graphs and graph databases. We're gonna be working with GraphQL shortly here. I think it's worth mentioning that in GraphQL, we are also working with a graph. We have types and objects and fields that connect other types and objects in the GraphQL type system. So this is where the graph and GraphQL comes in. So I think these data models, the property graph in the data model that we use in GraphQL, as you'll see in a little bit, are very, very similar. And when we're building full stack applications, it can really help to be working with graphs sort of throughout the stack from the front end to the back end. I use this news article example because that is the type of data we're going to be working with today. So I pulled down from the New York Times API this morning, it's either 25, I think, or so, or maybe 50 or so of the most viewed articles for the last week or something like that. So we're gonna work with that data set. And this is the graph model that we're going to work with. So we'll have article nodes. Those are gonna be connected to topics or organization or person that the article is about or mentions. We also have geo regions. So what geographic areas is this article about? And then we also have things like the author, the photo. This diagram has comments in here. I don't think we'll work with user comments today, but you can see how we would model comments on an article and comment threads, that sort of thing. The code for this is online on GitHub linked there. We're gonna be working with a separate GitHub repo, but this GitHub repo has some code for loading this data set from the New York Times API, to grab it directly from the New York Times API, you'll need an API key. But I, we don't need to worry about that today cause I just grabbed a slice for today, data that we'll work with. But this repo has some interesting things like working with this data in a Cloudflare workers or a couple of different ways of building GraphQL APIs.
6. Switching to Neo4j Browser and Querying Data
Switch to Neo4j browser from the Neo4j Aura console. Run the command 'colon play News Graph' in Neo4j browser. Wait for the Aura instance to spin up. If you have any questions, feel free to ask in the chat. Neo4j browser allows writing Cypher queries, visualizing results, and working with data. The data model consists of article nodes connected to topics, person, geo, organization, and photo. Return a count of nodes in the database, specifically 4,500 article nodes. View the properties of the article nodes.
Okay, so that's the data we're gonna look at today. What we're gonna do now is switch to Neo4j browser. So Neo4j browser is like a query workbench or working with Neo4j. So it allows us to write these Cypher queries, visualize the results and work with data. So it's kind of the main development environment testing and development that we use when we are working with Neo4j.
So we access Neo4j browser from within the Neo4j Aura console. So you should see this open with button. You click that and you have two options, Neo4j browser which is the query workbench for Neo4j that we're gonna use, or Neo4j Bloom which is more of a visual exploration tool. When we do that, we'll be prompted for our password. So that's the random password that was generated. So we want to grab that from whenever we saved it. And then we're going to run this command, colon play News Graph in Neo4j browser once we're signed in. And we should see something that looks like this kind of down at the bottom. This will bring in what's called a browser guide that has kind of like a carousel of text and embedded Cypher queries that we can click on to kind of go through our next piece of the workshop.
So I'm gonna go ahead and switch to Neo4j Aura and run this command to bring up the browser guide. And then we'll pause for a few minutes to give everyone a chance. It looks like my Aura instance is still spinning up. So we will have to wait a couple of moments for that. I think I think this is taking longer because I changed the region. I think what it does is it gives you a region by default, maybe that has more allocation available to it. So if your instance is spun up, let us know in the chat actually how many folks have a green mark here that says running. If you have that, go ahead and open up Neo4j browser. If not we'll just wait a few minutes. Antoine says, yeah, his is still in progress. Okay. Paul says the same. Okay, so we will just wait a few minutes, that is fine. Gabrielle says still waiting. Okay, yeah, that's cool. We'll give it a few more minutes to spin up. That is fine. In the meantime, if anyone has any questions, feel free to let us know in the chat if you have any questions and we can dive into those. Otherwise, I do have a Neo4j instance with this data loaded. So maybe we'll take a look at that. Cool, so this is Neo4j browser. I'm just gonna demonstrate what this looks like here and then when our Aura instance is ready, we'll switch back to Aura. So this is the Neo4j browser. You basically have a Cipher editor here, so we write Cypher queries here and then we get a frame, so one of these panes for each query that we write. So here I wrote a query that says match in in parentheses. So with Cypher, what we do is create graph patterns using this sort of ASCII art-like notation. So match, the match command is saying go find some data that exists in the graph based on this pattern and we're gonna define some graph pattern. So the most basic graph pattern we can define is think of it as a bare node pattern, I guess where we draw this sort of ASCII art representation of a node, which is like open and close parenthesis. And then this in, inside that parenthesis that becomes a variable that is bound to that piece of the graph pattern. So in this case, node that we can then refer to later. So first thing we do is we match on every node in the database, that's the simplest pattern we can. And these nodes then that match get bound to the variable in and then we can refer to that later on in our query. And we want to return an aggregation that is a count of the number of nodes in the database. So this data set that I'm looking at has 16,000 nodes. We can create more specific patterns. Here we're adding the label. So this colon article after the in, this is saying, find nodes that have the label article. So we said labels are kind of like a way to group nodes. In GraphQL terms, you think of this as a type. So when we start working with GraphQL, we'll see how we can map GraphQL types to node labels. So if we run this again, we have 4,500 article nodes. Let's look at the data model that we have. So DB schema visualization, and let's clear out the styles here. There we go. It's a bit more legible. So this is sort of the meta model that we're working with. So we have article nodes that are connected to topics, person, geo, organization, and photo. So this is exactly matching the slides here. This diagram that we looked at earlier. So this is kind of the end result of what we're going to be working with. But using this this information, let's see how we can create a bit more complex patterns. So first of all, we have like 4,000 articles so I can't just return all of the articles. Let's return in about limit 10. So here's some article nodes. We can click on these to view the properties. So here we're viewing the key value pair properties that we're storing on our nodes.
7. Traversing Graphs and Using Variable-Length Paths
I can traverse the graph visually by double-clicking on nodes, but Neo4j Browser is better suited for writing Cypher queries. We can add complex patterns to our queries, such as traversing from articles to related topics. By combining the variable-length path operator and the shortest path function, we can find the shortest path between nodes in a graph. This is useful for various use cases, like logistics, routing, social networks, and knowledge graphs. Let's look at an example of using the variable-length path operator to find the shortest path between two nodes, 'cheese' and 'Tik Tok'.
I can double click on these to traverse out the graph. I can see this is about a lunar eclipse and I can see the topics, eclipses, moon, Earth, space and astronomy, and then a photo connected to that. I wanna see what are other space and astronomy nodes. I can double click again and we do another traverse out. So I can traverse the graph visually this way, but Neo4j Browser is really built for writing cipher queries and working with the results. So rather than exploring visually, if you want to explore visually, that's where we would use Neo4j Bloom.
So let's add a more complex pattern to this. So let's say for these 10 articles, let's also see the topics connected to the articles and we'll return and so I'm just, and let's return star, which will return any variables that we match on. So now we've defined a little bit of a traversal in our graph. So we're searching for not just articles, but now we're drawing this sort of ASCII art representation of a relationship, and this kind of looks like an arrow that we've drawn here and these brackets indicate the relationship where I can specify the relationship type. So I wanna follow the HasTopic relationship coming out of our article nodes to these other topic nodes, and then I'm gonna return 10 of those paths. Let's return, say, 25 so we can get a little bit more visual representation. So here's a bunch of articles about exercise. A bunch of articles about exercise. We can change this also to order in the published. So now we should get the most recent, oh no, we get the oldest, in by published in descending order. By default, we get ascending order. So we want the most recent articles and their topics. And what's nice about Cipher is if the answer to our question is a more complex traversal through the graph, we just add a more complex graph pattern. So now if I want to say, okay, for all of these topics for today's articles, what are other articles that have those same topics? We just add that piece to our pattern. So now we're starting with most recent articles ordered by published date in descending order, traverse out to the topics of those articles, and then find other articles that are connected to those same topics. Let's make this, let's do, let's get a few more pads here. So 300, there we go. And ends up with lots of things about coronavirus and vaccine and so on, because there are lots of articles about those two topics in our dataset.
Okay, so that's a little look at Cypher. Let's switch back to Neo4j Aura. Looks like we're still loading here in Aura. Okey-doke. Let's keep looking at Cypher then. By the way, if you want to follow along, this database is public, there's the URL for it. I'll drop that in the chat. And there's a read-only user, which is newsgraph, and the password is just newsgraph. So you can open that up if you want to follow along. We have talked about Cypher. We have talked about Cypher writing graph patterns. We also have some more complex patterns that we can work with, such as the variable length path operator. Let me bring up the Cypher ref cards, helpful reference. So this is the Cypher ref card, which has lots of different information about Cypher, different commands and examples. So there's lots of functionality here for working with Cypher. One thing I wanted to take a look at is variable, variable-length paths. We have an example here. Yeah, here we go. Variable-length path. So this variable-length path operator is really, really powerful for working with graph data. Basically what this means is allows us to specify a variable number of relationships to follow when we, maybe we are interested in a node that's connected to another node, but we don't know if that's one hop away or five or 10 or 20. So what we can do is just include this asterisk in the pattern here. And that means find, in this case, in an M. So find a connection between N and M by following any number of paths. And we typically wanna specify an upper and a lower bound, we don't typically just wanna like keep traversing the graph. At Nauseum, typically, we have some upper boundary that we're interested in. So we can set that as well. So this is really powerful when we combine this with another super powerful function in Cypher, which is the shortest path function. So oftentimes, I'm interested in the path from one node to another, following a variable number of relationships, but I'm not interested in like the longest path often or just like one of many often I want the shortest path. So the shortest path function we'll take a pattern with a variable length operator in it and we'll do what's called a binary breadth first search. So find the two end points and then kind of iterate through the graph to find the shortest path connecting these two nodes. And this is useful for all kinds of different use cases, things like logistics and routing, also things like in social networks or even in knowledge graphs where I'm interested in two topics and maybe I want to recommend in our case, like articles that are sort of intermediate topics to our dataset. So let's take a look at an example of using variable length path operator. So I'm gonna say MATCH. Now here I'm gonna use a slightly different syntax where instead of where the variable is defined sort of inline in the pattern, I'm defining it out here and this is because what I'm going to work with is a path rather than just a piece of a pattern. But I'm interested in the shortest path and close some of these frames to get out of our way here. So I'm interested in oops, shortest path, shift enter will get you a new line if you want multiple lines in here. The shortest path from how about shortest path from cheese I was looking at this one earlier. Cheese to Tik Tok. So here I'm defining a node pattern. So looking for topic node and then these curly braces. That's how we indicate properties. So this says match on the node has the label topic where the value cheese for the key name. And then I think we have Tik Tok in here. I was thinking of this earlier. I think it's Tik Tok and then it's parent company, Bite Dance, something like that, and then return...
8. Traversing the Graph and Building GraphQL APIs
This part covers traversing the graph to find the shortest path from cheese to Tik Tok. We discuss the power of Cypher in Neo4j and check the status of our Aura instance. We then move on to building GraphQL APIs with Neo4j, explaining the similarities between the property graph data model and the GraphQL data model. We also provide an overview of GraphQL, its type system, type definitions, and resolver functions. Finally, we explore implementing a GraphQL API in the backend using resolver functions to fetch data from a database.
So this is gonna traverse the graph to find the shortest path from cheese to Tik Tok. And it ends up being kind of a short path. So here's an article about cream cheese shortage in New York that also has the topic quarantine. And there's another article here about social media influencers, which, of course, is connected to Tik Tok. I can double click on these to sort of expand out any other sort of intermediate nodes that are connected.
Okay, cool, so that hopefully gives you some idea of the power of Cypher that we can use with Neo4j. Let's check in on our aura instance. If it's not done yet, we might just go ahead and move on. I'm assuming everyone else is still says waiting to spin up. Aura must be having a slow day today. All right, well, let's go ahead and move on since we don't want to spend all of our time just waiting for our Aura instance to be ready. That's fine, we can just use this news.graph.zone database. That is fine. So that kind of covers the first module about Neo4j. If there's any questions that folks have, definitely let us know in the chat. Oh, you can also, in Zoom, you can raise your hand if you want to speak to ask a question. So you go ahead and do that. If you have a question about Neo4j, just click the raise hand and then it'll send me alerts and we can get your question that way. If you don't want to put it in the chat, but chat is fine as well.
9. GraphQL Resolvers and Benefits
The N plus one query problem occurs when multiple round trip requests are made to the data layer, resulting in performance issues. This can be addressed using the data loader pattern or database integrations. The Neo4j GraphQL library can auto-generate resolver functions and optimize database queries, solving the n plus one query problem. GraphQL allows for precise data fetching, avoiding overfetching and underfetching. However, it presents challenges in areas such as error handling and caching, requiring different approaches than REST. Despite these challenges, GraphQL offers significant benefits in terms of efficient data retrieval.
And then do the same thing for theme and do the same thing for recommended. So you can see because of the nested way that these resolver functions are called, we can often end up making multiple round trip requests to the data layer, to the database for each of our selections, essentially, in our nested selection set. So this is what's called the N plus one query problem where we end up making multiple round trip requests to the data layer. And this has performance problems because each of those round trip requests to the data layer incurs some overhead to be much more efficient because we can just make one request to the data layer and all of our data comes back.
So the N plus one query problem, this is something that if you've built graphical APIs before that you will run into. There are a few different ways to address this. One is called the data loader pattern where we can cache and batch data so that, first of all, we figure out, okay, what are all of the queries that we're gonna send to the database and then we kind of send them all at once? Or we can use database integrations that generates a single database, query from the root resolver based on our GraphQL request. And that's what we're gonna do today with the Neo4j, GraphQL library, which will do two things related to resolvers. One is first of all, it will auto-generate all of our resolver functions for us. So we don't have to write any of this kind of boiler plates data fetching logic. But also, and equally as importantly, I guess, it will generate a single database query from the root resolver. So that takes care of the n plus one query problem. It sends a single database query to the database. The database can then figure out how to optimize that request, okay.
So that's GraphQL resolvers. What are some of the benefits of GraphQL in general? I think this idea of overfetching and underfetching is important where we're sending exactly the data that the client has asked for, nothing more, nothing less. And the client is able to construct a query that says, give me all of the data that I need to render this view. So the client does not have to make multiple requests to the API layer. It's a single API request to fetch all the data that the client needs. I think that's really one of the key benefits when working with GraphQL. Of course, there's lots of challenges that come up when working with GraphQL. We talked about the N plus one query problem, but also I think in general, one of the main sort of categories of challenges is that a lot of the well understood practices from rest don't apply in GraphQL. So things like HTTP status codes, error handling, caching, those things are all handled a bit differently. There's tooling and best practices to address all of these, but these are some things to be aware of.
10. Using GraphQL Playground and Querying the API
We are going to use GraphQL playground today to query our GraphQL API. Playground has been deprecated. Instead, you'll see things like GraphQL or Apollo studio that enable us to query a GraphQL API from within the browser, taking advantage of introspection. Let's open the GraphQL playground and familiarize ourselves with the API structure. Spend a few minutes working with the API, querying and exploring the available data. This API queries the same Neo4j database we looked at earlier. Let's pause for a couple of minutes to write some GraphQL queries and get a better understanding of the data we'll be working with.
We are going to use GraphQL playground today to query our GraphQL API. Playground has been deprecated. So you will probably see less and less of it going forward. Instead, you'll see things like GraphQL or Apollo studio has a, what's it called? Explorer, I think, is the function in Apollo or the feature in Apollo server, Apollo studio rather. But it's all similar tooling, basically tooling that enables us to query a GraphQL API from within the browser, taking advantage of a feature of GraphQL called introspection. So we can introspect a GraphQL API, that says, hey, tell me the types, the data available in this API. That's introspection. Once we have that, we can then build tooling that gives us, say like documentation of the API. What are all of the entry points? What are all of the types of the API? Or tooling like autocomplete, as I'm writing my query, I can get autocomplete, because I know what fields are available, the types of those fields, and so on. So we're going to use GraphQL playground today. So to get familiar with GraphQL playground, and also with the API that we're going to be building, let's take a look at an example. So let's go ahead and open this URL in a browser, and I'll drop a link to this in the chat. So news-graph.beursel.app slash API slash GraphQL. So that will open GraphQL playground. And what we wanna do is spend a couple of minutes just familiarizing ourselves with the structure of this API and also with GraphQL Playground if we haven't used it before.
There's a couple of queries here. I'll copy paste these in Discord. Maybe that's easiest. So if you're in Discord in our channel, here's the first query and here's the second one. Otherwise, if you have the slides up, you can just kind of copy and paste these but just give these a run in GraphQL Playground. Take a look at the Docs tab to see what data is available. Play around with the Control Space auto-completes to see, for example, in articles. Can you also include topics? Can you also include things like the geo region? And so on. So let's spend a few minutes working with this. This GraphQL API is querying that same database in Neo4j that we looked at earlier. So if we look in the Docs tab, we can see we have articles. We also have count and aggregates. We can also do aggregations. We can look for articles, authors, topics, and so on. So here we're looking for, make this a little bigger, four topics where the name is movie. So topic movies, and then what are all of the articles connected to the topic movies? And we can see things that we can do. For example, just show me 10 articles. We can also grab the URL, the published date. Maybe we want to know organizations that are mentioned or other topics for each one of these. So let's just spend a few minutes querying this API, give us some ideas of what kind of data we are working with. So again, I dropped a link to that in the chat and some of the example queries, I'll bring that back on the screen. But let's pause for just a couple of minutes to give folks a chance to write some GraphQL queries. And this is the exact API and data that we're going to build the GraphQL API for in the next step. So in the next step, we'll see, how do we create the code for this API? So I'll pause for just a couple of minutes and again, ask any questions or issues that you have in the chat.
11. Implementing API with Neo4j GraphQL Library
Let's implement the API using the Neo4j GraphQL library, which allows for GraphQL first development. We define our types and their connections, which drives the data model in the database. This eliminates the need for multiple schemas and simplifies development.
Just let us know. Okay, did everyone have a chance to write some GraphQL queries? And anyone uncover anything interesting or an interesting GraphQL query or this API? If you did, feel free to let us know in the chat. So let me see if that's in the chat. Cool, so that, I guess, familiar with GraphQL playground and writing GraphQL queries and the API that we're gonna build.
So let's talk about some goals of the Neo4j GraphQL library. Well, the first one is this idea of GraphQL first development, where we wanna take our GraphQL type definitions. So we start there, we define the types, how the fields available on the types, how that data is connected, and then that drives the data model in the database. So we don't need to maintain multiple schemas for the API, for the database, instead our GraphQL type definitions define everything.
12. Query Validation and Early Error Detection
AC asked if errors can be caught during query creation time instead of after running them. In GraphQL Playground, syntax errors are indicated with red lines, allowing for early detection. This is possible due to introspection, where the playground knows the object field requires a sub-selection. The client-side query validation process helps identify and fix syntax errors before sending the query to the server.
So before we move on, I see a good question in the chat from our previous exercise. So let's switch back to Playground. So AC is asking, can we catch errors during query creation time instead of only knowing after running them? Field topics. Must have a selection of subfields. Yeah, this is a good one. So for example, so you might get this error. Let's say, let's just look at some articles. Here, we've got 10 articles. I'm gonna bring in title and URL. And if we look in the docs for articles, we can see that, okay, yeah, we've got topics connected to the article. So let's grab topics. So we can add topics here. But if we run this, we get an error. And I think this is the error that the AC posted in Discord. That we'd have a selection of subfields. Did you mean topics? GraphQL validation failed. And yeah, so what this error is saying is that topics, this is a object array field. So this is like a reference to topic nodes in the graph. And I can't just return these topic objects. I need to, in my selection set, define which fields I specifically want to return. That's sort of the way that a GraphQL selection set works is that I have to define my selection set, these scalars that I want to return for any object field. So AC's question was, how do I know that there's an error here before I actually send the query to the server? And one thing in GraphQL playground will give us this, if you can see it here, but there's a small red line here on line five, that's indicating there's some syntax there. If I highlight over that line in GraphQL playground, I can see this is telling me the client side error. So I can see this before I send it. And this is this idea of introspection where GraphQL playground knows this is an object field. So it's giving me the error here and telling me that, well, I need to add a scalar selection in GraphQL playground. AC says it doesn't have the red indicator. Okay, that's not good. That's one way I guess is just in GraphQL playground sort of an other tooling as well, like there if we're in DS code and we are writing code, which will jump to working with code in a minute here. And we're writing code. If we have the GraphQL extension installed and it's pointed at our API, it can introspect the API and know that, Oh, this is an object field needs to have a sub-selection. So, AC you posted that screenshot. What if you remove the name selection under TopX? So, you just leave, it just says title URL and TopX. Do you have the red squiggle then, if you remove name? Okay, cool. Yeah, so you see it there. Yeah, so this, we fixed our syntax error, then the squiggle disappear. Yeah, so that's the client side sort of query validation process happening there. Cool, yeah, so that's a super helpful, super helpful feature is being able to introspect the API and use those types in tooling, both things like GraphQL Playground and then also other developer tooling.
13. Goals and Features of Neo4j GraphQL Library
The Neo4j GraphQL Library allows for GraphQL first development, generating GraphQL API operations based on defined types. It translates GraphQL requests to single Cypher queries, eliminating the N plus one query problem. CRUD functionality is provided without additional code, and custom logic can be implemented using the cypher-graphql-schema directive.
Cool, so we're talking about the Neo4j GraphQL Library and talking about building this API layer that sits between the client and the database. What we are talking about now are the goals of the Neo4j GraphQL Library. So we said it's idea of GraphQL first developments where we define our types, our GraphQL type definitions and that drives the data model in the database. Once we define our types and hand those off to the Neo4j GraphQL Library, the Neo4j GraphQL Library will generate GraphQL API operations. So specifically we'll generate the query and mutation types with entry points for by default, every field, every type in the schema and add things like ordering, pagination, filtering, aggregations, these sorts of things. So, we don't have to define all of those, those are just generated based on the types.
Then at query time, the Neo4j GraphQL Library is going to take a GraphQL request and translate that to a single Cypher query. So we saw some examples of Cypher earlier where we were drawing traversal, drawing like ASCII art representations of traversals through the graph. You can think of that as kind of mapping to like a nested selection set. A nested selection set is also defining a traversal through the graph. So by generating a single database query, this means that we're getting rid of that N plus one query problem where we might make multiple round trips to the database. And instead, we send a single Cypher query. The database figures out how to optimize that and go from there.
So far the features we've talked about have been kind of like CRUD functionality. So we get create, read, update, and delete operations for every type we define basically without writing any additional code. But what about if we have custom logic? So let's say, for example, we wanna generate personalized recommendations. Well, to do that, we can use what I think is my favorite and probably the most powerful feature of the Neo4j GraphQL library and that is the cypher-graphql-schema directive. So GraphQL schema directives, these are like annotations in our type definitions that indicate that there is some custom logic that should happen on the server. So schema directives are GraphQL's built-in extension mechanism.
14. Custom Logic with Cypher-GraphQL-Schema Directive
The cypher-graphql-schema directive allows us to attach custom logic to a field in GraphQL using Cypher. For example, we can traverse user reviews to find recommended businesses. This is called collaborative filtering graph traversal. With this feature, we don't need to write our own resolvers and can send a single query to the database.
The cypher-graphql-schema directive allows us to basically attach a cypher statement to a field in GraphQL to define some custom logic. So in this case, this example, we have a recommended field where we are returning recommended businesses. So for example, we may do that by traversing user reviews. So this comes from a data set where we have user reviews of businesses. So we can say for the currently resolved business, that's where this keyword comes in. For the currently resolved business, find all the users who wrote a review of this business. And then what other businesses are those users reviewing? That might be a good recommendation. Right, so if you like this business, what are other businesses that you like? That's an example of what's called a collaborative filtering graph traversal. We can basically use this cipher schema directive feature to attach custom logic, define using basic, any functionality that we can define in cipher. So super powerful. We don't have to write our own resolvers and that cipher query that we attached to our schema, that gets attached to the generated, the single generated database query. So we're still just sending one query to the database.
15. Building a GraphQL API with Neo4j
Let's take a look at a quick start example of building a GraphQL API with the Neo4j GraphQL library. We install the necessary dependencies, define the GraphQL type definitions, create a connection to the database, and generate an executable GraphQL schema using the Neo4j GraphQL library. With minimal code, we can run the GraphQL playground locally and query our API, similar to the articles API we saw earlier.
So that's why we use the relationship schema directive to define the direction for the relationship in the database. So in this case, we're saying that the genres field on movies in the database that follows the in genre relationship with the out directions of going from movie to genre. So the next thing we're doing is creating a connection to our database using our connection string for the database. In this case, username and password. And then we take the type definitions that we wrote earlier, and this Neo4j driver instance. We pass that to the constructor of the Neo4j GraphQL class. This comes from our Neo4j GraphQL library. And then that gives us a executable GraphQL schema that we pass to Apollo Server that can then handle the networking aspect of our GraphQL API.
Note that we didn't write any GraphQL resolver functions. We didn't write any like boilerplate code that specifies how to fetch data from the database. All of that was handled for us by the Neo4j GraphQL library. So that was all in a single file. If you run that, we would see GraphQL playground running locally. So now we can query our API. So this is an example from a book's API. This is pretty similar to the articles API that we were just looking at in GraphQL playground because the generated API is both generated using the Neo4j GraphQL library.
16. Neo4j GraphQL Library and Graph Modeling
The Neo4j GraphQL library handles operations like create, read, update, and delete. It translates GraphQL queries to Cypher queries and supports sorting, pagination, and filtering. The library also allows for nested filtering and sorting. Geo data and relationships can be filtered using nested structures. Graph diagrams can be created using tools like arrows.app, which can generate GraphQL type definitions. This iterative graph modeling process helps define the entities, relationships, and queries in the API.
All of that was handled for us by the Neo4j GraphQL library. So that was all in a single file. If you run that, we would see GraphQL playground running locally. So now we can query our API. So this is an example from a book's API. This is pretty similar to the articles API that we were just looking at in GraphQL playground because the generated API is both generated using the Neo4j GraphQL library. So the filters, the query entry points and so on. I'm going to go through this a little bit quickly, but I do want to touch on some of these concepts and then we'll start writing some code.
So by default, every type has a create, read, update and delete operation generated as a field on the query and mutation type that maps to node labels in the database. And of course we can construct arbitrarily complex GraphQL queries and those are translated to Cypher queries and sent to the database for us. We've seen some examples of this already for sorting and pagination, we have this options argument in our query fields that allow us to do sorting, limiting, offset for pagination. We can also do cursor based pagination using a relay style connection types. So you'll notice that for our relationship fields, you'll also see the name of the field connection and those map to relay style connection types that support cursor-based pagination. For filtering, we saw an example of this where we were filtering for a movie by title. The inputs generated here depend on the type of the field. So for numeric fields, you have greater than, less than, equals, that sort of thing for string fields, we have the string comparison operations like starts with, ends with, contains those sorts of things. We can do nested filtering and sorting as well so that where arguments can be applied at the root and also nested in the selection set. But just note that the filtering is applied at the level in the selection set where we use it. In this example we're searching for books with a price of less than $20. And then for all of those books, reviews that were created after January 1st, 2021. This is not saying only show me books that are less than $20 in price and have reviews that were created after this date. So we may not see any reviews if we're filtering because the filter is applied at the level in the selection set where we use that argument. We can work with geo data. I don't think we have point geo data that we work with today, but we can use filters if we have points, latitude, and longitude data. Here's an example. So I said just a minute ago that the filters are applied at the level in the selection set where I used them in the arguments. So for example, if we want to filter through a relationship, so here in the book example that we were looking at, we had orders, and then we have address nodes that are connected to orders, and address have a latitude and longitude point type on them. We want to filter for orders where the location is within a certain distance of a point. So that's being applied based on a value on the address node. We want to filter order nodes based on that. Well, to do that, we just use a nested structure in the where argument. So we're saying where the ship to, which that's the relationship field to the address, where the distance is less than one kilometer from this point. So now in this case, because we applied the filter at the root by specifying the argument here. Now we're filtering orders based on the relationship to address nodes. Cool, so that's the Neo4j graphics kill library. You can see a big part of driving the configuration for the API is all about the graphical type definitions that we write. So we drew our graph data model already. We saw that we have data on articles, topics, geo-region and so on. So what we're gonna do is define graphical type definitions that define that data model. Zoom in a little bit here. This is a little easier to read. So what we've done here, we're defining a type topic. Topic has fields like title, URL, and then relationship fields to the author, the topic, person, organization. So you can see we're using this relationship schema directive to encode the direction of the relationship and the type of the relationship. We're also using the exclude directive here. This is gonna be a read only API. We don't want to support, create updates or delete right now. So we use the exclude directive to basically say, hey, don't generate mutations for this type. So these graph diagrams were all created using this tool arrows.app, which I'll drop a link to in the chat as well. Arrows.app. So arrows is nice because it allows us to create these graph diagrams. So I can just sort of drag out nodes. A video might have, I don't know, maybe this has a rating. Oops, this is supposed to be a node label. Not a caption, there we go. A node label. Video has, I don't know, let's call it a rating or something like that. Contrived example. But it allows us to create these diagrams, which we can then save the images. We can also export, say like the JSON that defines us and check that into version control, that's quite nice. But we can also generate the GraphQL type definitions based on the diagram we created. So we go through this graph modeling process, which I think is really this iterative process where we figure out what are the entities that we're interested in, how are they connected, those become relationships. and we look at a traversal through the graph to sort of think of can we answer the questions that we have. If we can, then our model is complete and we can sort of just generate our GraphQL type definitions that define that graph model. These are the type definitions that work with the Neo4j GraphQL library. That can be a good way to go through this data modeling process and come out with the definitions that match the API you want to work.
17. Setting up Next.js with Neo4j
We discussed the Neo4j GraphQL library and how to write GraphQL type definitions. Next.js is a full stack React framework with features like server-side rendering and file-based routing. We can define API endpoints in our Next.js app using API routes. We provided a GitHub repo with starter code for a Next.js application. We explained how to clone the repo, update environment variables, and run the Next.js app locally. Let's pause for a few minutes to allow everyone to follow these steps.
Okay, so we talked about the Neo4j GraphQL library. We talked about how to write GraphQL type definitions based on the data model that we want to work with today, articles, topics, and so on. Let's actually take a look at some code and get this running with Neo4j.
Cool. So let's take a look at some code and working with GitHub and Next.js. So there is a starter... A starter GitHub repo. Let me copy the link here. So this links to a GitHub repo that has some starter code for us and a Next.js application. So what we want to do is open that link in GitHub. This is a template repo, which means that what we want to do is instead of cloning this repo, we want to click on use this template, which will create a new repo which will create a new repo under your GitHub user. And then what you want to do is clone that repo that was created from a template of this one. And the reason for that is because we're going to use Vercel to deploy this directly from GitHub. And so it's easier than if you pull down everything from this repo and then go through the steps of creating your own repo and so on. You can just do that with one click, use this template.
So we're going to do now. We're going to pause for a few minutes and go ahead and open this repo in GitHub, click on use this template. Now we'll create a new GitHub repository. And then when you created the new one, what you want to do is clone that GitHub repo and then follow these steps here to get the next.js app running. There's a step in here to update the environment variables, but I think there may be an issue with provisioning our Aura instances. So we'll just use the, that default database, which is already filled out in the, dot env. So let me go through this so you can see what this looks like. And then, and then we'll pause for a few minutes to give everyone a chance to go through this as well.
So I'm gonna go to dev.nufja.com slash fullstack-graph-repo. That link is pasted in the chat. So this is a starter project Next.js app for the workshop today. I'm gonna click, use this template. You need to give it a name. Let's call this, GraphQLGalaxyNil. fullstack-graphql-workshop. And click Create Repository From Template. You can call it whatever you like, of course. So that's using that template repository to create a new repository under my username, cool. And what I wanna do is now clone this repo. I'm gonna go under the Code tab here, copy the link to it. You can do either SSH or HTTPS if you don't have an SSH key configured. And then in the terminal, zoom in, do git clone, paste that link, and then I have a password for my SSH key. Cool, and then I'm gonna CD into the directory that was created when I cloned that repository. And let's open this in a code editor. So I use VS Code, so I'm gonna open this in Code Editor and bring that over. And so if I look at this, here's the README. There's a data directory, an image directory, which we don't need to worry about, and then a next JS directory. So all of the code are interested in is in this next JS directory. Zoom in a little bit here, probably good. And so in next JS, we have a few things, we'll do a walkthrough of the code in a minute here, but just for the initial setup, we said to update.env.local to fill in your Neo4j-Aura connection string. But I think there's some issues with Aura, so we'll just use this default one, this should still work for everyone, just the read only database user. So just leave.env.local, you can just leave that as is. And then I wanna open up a terminal. And in CD next JS, we're gonna do npm install or yarn, if you use yarn, that's fine too. This is gonna install our dependencies. And then I'm gonna do npm run dev. And this is going to start this next JS application and run it locally, in my case on port 3000. So if I now go to local host 3000, I should see this, which is the welcome to next.js, this is the basic app that you get when you create a new next JS application. Cool, let's pause there to give everyone a chance to go through those steps. If you get stuck with anything, if you have any questions, ask in the chat. What we want to do is open the template repo in GitHub, click, use this template to create a new GitHub repo under your GitHub username, clone that repo. And then open that up in a code editor and in the terminal, do an npm install and npm run dev. And if you see, if you see something that looks like this, then you're good. So hopefully that was enough time for everyone to create a new repo, clone it, and run your Next.js app.
18. Analyzing Code and Theme in Next.js
AC posted a screenshot of his setup. We encountered an issue with Aura instances not spinning up due to an AWS DNS outage. AWS is resolving the issue. Now, let's focus on the code. We have a basic welcome page in Next.js. Let's dive into VS code and check the theme. If you have any trouble reading the code, let me know.
AC posted a screenshot, looks like he's got his setup. That's great. Was anyone else able to get that going? If not, let us know. Oh, I got some more information about the Aura issue. So let's see, did our Aura instances ever spin up? No, it doesn't look like it. So apparently, there's a AWS DNS outed to the storage, which is preventing AWS from processing these create database requests. So yeah, that is why we can't provision new instances. So AWS is resolving that, I've got a ticket and no. All of those database create requests will be completed once the issue is resolved. So glad to know it's not just us. Okay, cool, so we've got this repo up and running. Let's take a look at the code and see what's going on. No thanks, Robert. Oops, I don't know why it keeps prompting me to update one password. Don't, don't need to worry about that now. Cool, so here's our basic welcome to Next JS page. Let's jump into VS code. Is this theme okay? Maybe I can change this to something a bit more readable. This one, I think I've had good luck before with on videos. Anyway, let me know if that's not legible.
19. Dependencies and Code Structure
In the Next JS app, we have dependencies for React, Next JS, Neo4j driver, micro, GraphQL, Apollo server, Neo4j GraphQL library, and Apollo client. This allows us to have one code base for both the React app and the GraphQL API.
So let's take a look at what's going on here. So first of all, in the next JS directory, this is where we have our Next JS app. And first off we can look at package JSON to see what dependencies we're pulling in. We're pulling in React and React dom and Next JS, and we're pulling in Neo4j driver, micro which is a web server, and GraphQL, the reference implementation. And then we're pulling in this micro flavor of Apollo server, micro is a web server that works well with Next JS, which is why we're using that. We'll see where we're using that in a minute. And then we're also pulling in the Neo4j GraphQL library and Apollo client. Apollo client is a tool for querying GraphQL APIs. So you can see here, we have a couple of like front end and backend things mixed. We have basically the dependencies we need for our React app and like Apollo client for data fetching into our React app. But then we've also installed the dependencies we need for building our GraphQL API as well. So all of that is in one Next JS app, which I think is pretty neat, is handy for sort of having one code base to work with.
20. Next JS File-Based Router and Data Fetching Basics
Next JS uses a file-based router with hot reloading. We can create new pages and get new routes. The articles page displays a list of articles fetched from our GraphQL API connected to Neo4j.
Next JS, by default when we go to localhost 3000, Next JS uses a file-based router. So in the pages directory, we have a few different pages, we have index JS. And index JS, this is what we see when we go to localhost 3000. So here's where we have the welcome to Next JS and basically everything that's rendering this screen. So if we edit that, we could instead say welcome to full stack GraphQL and we have hot reloading. So that updates right away, which is super cool. So that's kind of the basic for the front end. If we create a new page, we'll get a new route. We can see there's one here for articles. So if we go to local hosts, 3000 slash articles, we can see we have a honored list of articles. So we have these are links. You can click on one. This is data coming from our GraphQL API reading data from Neo4j and just showing us a list. So I warned you earlier that we were not gonna focus too much on the front end. But we'll improve this a little bit but just kind of want to touch on the data fetching basics first.
21. Setting up API Routes and GraphQL API
We explore the API routes feature in Next.js, which allows us to define API endpoints in our Next.js application. These endpoints are deployed as serverless functions. We demonstrate how to create and modify API routes, such as /api/hello and /api/graphql, which map to specific functions in our code. The /api/hello route returns 'John Doe' as a JSON object, while the /api/graphql route provides a GraphQL playground to interact with our GraphQL API. We examine the code responsible for setting up the GraphQL API, including dependencies, type definitions, and the Neo4j driver instance. We discuss how the code generates a GraphQL executable schema and passes it to Apollo Server. We also cover the use of environment variables and the debug mode in the Neo4j GraphQL library.
So this data is coming from our GraphQL API which is coming from Neo4j but where's the GraphQL API running? So that's the next thing we wanna look at. So we talked about Next.js having this file-based router where we create a new file and that maps to a route. So we have index, we have articles slash articles but we also can have API routes. So let's take a look at the docs for this. So this is a really cool feature. So API routes, this allows us to define API endpoints in our Next.js application. And so the convention here is anything inside the API directory inside the pages directory gets mapped to a API route at that endpoint. And when we go to deploy this, we're gonna use Vercel to deploy this in a minute. Each of these endpoints gets deployed as a serverless function. So, I think we have slash API slash hello, so if we go to slash API slash hello, we get back John Doe. If we look in our code in pages API hello JS, this is the function that is called. We can change this to return, so returning a JSON object, let's change this to return full stack GraphQL. We'll save it and again, so that hot reloading, we get that updated. So, we also have an API route, GraphQL. So, API slash GraphQL, we should see GraphQL playground and, oops! I have a old query variable. Don't need that. But here, this is just should look familiar to us, this is very similar to the GraphQL API that we were running in one of the exercises, we were writing queries and search for articles and so on. And that's exactly what we have locally. So, let's take a look at what's going on in this code. This is gonna be the, kind of the starting point for our GraphQL API. So, we're pulling in some dependencies, we're pulling in Apollo server from this specific micro version, again, micro is a web server that works well with next.js, which is why we're using that, then with the latest versions of Apollo server, Apollo studio is the defaults, you kind of get when you open a GraphQL endpoints, you get like a redirect to the hosted Apollo studio. I'm using Apollo, I'm using a GraphQL playground here. So I like being able to just open the endpoints and you have Apollo or GraphQL playgrounds right there to work with, but really it's the same functionality. Actually Apollo studio, I guess now has more functionality than playground. Anyway, that's why we're pulling in this GraphQL playground landing page plugin. We're pulling in the neo4j driver and neo4j GraphQL library. Then we define our GraphQL type definitions. So we saw these earlier, basically we are creating types that map to the graph model that we created in neo4j. So we have articles, authors, topics, persons, organizations, geos, and photos. And all of these types have an exclude schema directive, which allows us when we generate the API to exclude create update delete. So no mutations are gonna be generated. And in fact, we can verify that if we go to GraphQL Playground, look in the Docs tab, no mutations show up. This is the read-only API, we only have query operations. We're also using the relationship schema directive to encode the direction of the relationship. So this matches exactly this model, which we do call db.schema.visualization in neo4j. And let's do a style reset so we can read it. This matches this graph model that we have in the database. Now let's do a style restart. We create a Neo4j driver instance. We're reading the connection string and username and password from environment variables. And that's set in this dotenv dot local. Typically, you wouldn't check in the dotenv file but for the purpose of having a skeleton that works out of the box, we've done that. So by default, we're pointed at this news.graph.zone Neo4j instance, which is that same Neo4j database that we were querying earlier using this news graph read-only user. So XJS works with these dotenv files. So we're setting those here. Later on when we go to deploy this with Vercel, we'll have to set these environment variables in Vercel to kind of override this dotenv file, because we shouldn't really have that checked into GitHub. We are also setting a couple of other environment variables. Debug, we'll talk about that one in a minute. And we'll also talk about this next public GraphQL URI. So we'll come back to those. Oops, that's not what I wanted. I want pages GraphQL. Okay. So that's where our environment variables are coming from. We then pass the type definitions and Neo4j driver instance to Neo4j GraphQL constructor. And we get back a GraphQL executable schema that we pass to Apollo server. We're also like enabling playground and making sure enabling introspection by default in development mode. These are enabled, I think in production by default, playground introspection, I think are disabled for security reasons. So we're explicitly enabling those. And then we define the start server function. The start server function, we just have to start our Apollo Server instance before we can reference it in the handler. Remember this gets deployed as a serverless function. So this looks a little bit different than the syntax that we were just running this as a regular note app with Apollo Server. But basically we're defining the path which is last API slash graph as well that Apollo Server is going to serve our endpoint. Cool, so that's the basic code for our GraphQL end points. So that's running locally as part of our Next JS app which is running here. So you saw one of the environment variables that we set was debug. And it had a value of Neo4j GraphQL colon star, I think. Yeah, so this one. So what's going on here? Well, this is enabling debug mode in the Neo4j GraphQL library, which we can see in the docs.
22. Debugging and Query Translation
Let's go to the docs for the Neo4j GraphQL library and set the debug environment variable to log all debug info. We can run a simple GraphQL query to retrieve the title of the first 10 articles. The query is translated into a Cypher query that is executed against the database to fetch the requested data. The Cypher query matches article nodes and returns the article titles with ordering and limiting.
Let's go to the docs for the Neo4j GraphQL library which I linked these in the slides, but this is a good reference document to have available. Specifically in the troubleshooting section, where we talk about debug logging by setting this environment variable. So if we set debug equals Neo4j slash GraphQL colon star, that will log basically all debug info that is generated from the library, which is what we want. So what is this? Well, let's run a simple GraphQL query here. Let's just return title of the first 10 articles. When we do that, if we go back to our code and look in the console, we can see quite a few things here that were logged. Basically, it's saying of an incoming GraphQL request, here's the GraphQL request, there are no GraphQL variables, we have not enabled off so there's no JSON web token to talk about. And then that GraphQL is translated into this Cypher query. So you can see here the Cypher query that is generated and run against the database to resolve the data that we requested in GraphQL. And we can see here what's going on is we're matching on article nodes and then we're doing kind of a projection where we're returning just the title of the article and then doing our order in limit here.
23. Data Fetching and Front-end Configuration
Now, if we add more fields, we can see our generated cypher query is more complicated. We're returning title, URL, and topics. The cypher queries we're generating project a single object that matches the data our GraphQL API expects. On the front end, we have a simple articles component that fetches data using Apollo Client's useQuery hook. The component maps over the articles array and renders a list of article titles linked to their URLs. We configure Next.js to work with Apollo Client in the _app.js file, creating an Apollo Client instance and setting up the cache. The Apollo Provider wraps the top-level app component, making the Apollo Client instance available to all components in the application.
Now, if we add more fields, so let's also return the URL and let's also return topics. If we run that query, now we can see our generated cypher query is a bit more complicated. This looks a little bit different from the queries we were writing earlier, but because these are generated programmatically using a map projection and pattern comprehension features of cypher which typically you find it easier maybe to write like one long match pattern rather than to project out patterns that you want to return, but that's valid in cypher as well. That functionality is actually inspired by GraphQL and cypher. Anyway, so here we can see we're returning title URL and then for the topics in the object that we're returning, here's where we're doing the traversal where we're traversing from the currently resolved article node to find topic nodes that we're connected to and returning the name of those topics. So really the cypher queries that we're generating are projecting out basically a single object to be returned that matches the data that our GraphQL API is expecting to return. Cool.
So that's the back end, that's our API endpoint as an API route in next.js. We saw we have this very simple, if we go to local host 3000 slash articles, we have this very simple list of articles that we're returning, which link to some of our data from the New York Times API. So let's take a look now at the front end for this articles component, how that works. Okay, so now I'm gonna go to pages articles JS, and this is pretty simple component, we're pulling in the use query React hook from Apollo client. So Apollo client has the functionality to look at queries and the size, and it has integrations for lots of different front end frameworks. So we're using XJS, which is built on top of React, so we're using React flavor of the Apollo client integration, which I think is kind of like the default integration that you get. The use query hook, this allows us to basically define and then we have this hook available in our React components that we can use to work with data fetching. This is kind of the simplest way we can do that is by defining a GraphQL query. So here we are, we wrap this in the GQL template tag. This GQL template tag comes from Apollo clients import as well. This is what this is doing is parsing our GraphQL query. And we're searching for, what is this, the 25 most recent articles and then grabbing title URL and publish. So here's our React component. We don't have any props. Our data comes from a call to the use query hook and we're passing the article query that we defined here. So this is going to go out to our GraphQL API to fetch data based on this query. And then this data object will contain our result data. There's also loading state and an error object as well that we can pull in here to check if we are currently loading or if there's an error, but we're not handling those cases here. We are just returning an unordered list. We are mapping over articles. So this query, so we can just copy this, run this in GraphQL Playground. So this is the data object that we are working with in our React component. So we have data.articles, and that's an array of these article objects where we have title URL and date published. So we map over that articles array and return a list item that is basically just the title of the article linked to the URL of the article. So pretty simple, and that is what renders this list. So these are the 25 most recent articles from our GraphQL API that comes from Neo4j. One other thing I want to mention while we're talking about the front end data fetching aspect and that is, how we configure Next.js to work with Apollo clients to fetch GraphQL data and that is in this underscore app.js file. So this underscore app.js file this is kind of like if we need to inject things into our applications React component hierarchy, this is where we come to do it and that's exactly what we've done here. So we're pulling in Apollo provider, Apollo client, in-memory cache and HTTP link from Apollo clients. Then this function create Apollo clients is first creating a new instance of HTTP link passing in a URI. So what is HTTP link? Well, Apollo client for the networking layer has this concept of composable links. You can think of this as maybe like a middleware kind of thing where I can sort of have multiple links where my request goes through multiple sort of middleware processing. In this case, this is just creating a connection to our GraphQL URI, which we specify as an environment variable. And that comes from r.env.local. So our next public GraphQL URI is slash API slash GraphQL, which is where our API route is running. The reason this is next public is this isn't a real environment variable because this is client code, right? So this is code in the browser where there isn't really a same concept. So next js, let's bring up the docs for this. Next js environment variables. We jump this link in the chat here. So this talks about, we can set values in r.env.local and those are set as environment variables and available for data fetching in the API route. So that's what we did to set our connection credentials for Neo4j. But then for exposing environment variables to the browser, anything that we prefix with next underscore public underscore and that basically gets rewritten in the code that's sent to the browser. So it allows us to kind of use the same idea as environment variables here. And this is fine, we can expose this. Doesn't really matter if the client knows where we're running our GraphQL API. That's perfectly fine. Underscore AppJS, there we go. So we create a new HTTP link that just basically is telling Apollo clients what GraphQL endpoints to send requests to. And then when we create our Apollo client instance, we also need to create a instance of the cache. So other than having really great front-end framework integrations, another thing that Apollo clients does for us is maintain a cache. So that if we send another GraphQL request, requesting same data, the same objects, instead of fetching that data again from the server, we can cache it in our client application and that data is just read out of the cache. We can of course have different types and control over the cache implementation. The simplest one is this in memory cache. It could be like reading from a Redis cluster or something like that. So then down here, we are wrapping the sort of top-level app component for our next JS app with the Apollo provider. So this is the provider syntax in React allows us to inject things into the React component hierarchy using what's called the context API. So here we're injecting our Apollo client instance. So now that Apollo client instance is available to any component in our application, which is why if we look at our articles component, that instance of Apollo client is available for our use query hook here. So it knows exactly what graphic endpoint we're talking about. We don't have to like configure our graphical endpoints in each component where we have data fetching code, which is quite nice. Okay.
So that I think is a pretty good sort of whirlwind look at the code here. What we wanna do next is deploy this so that instead of running locally on our machines that it lives in the cloud.
24. Deploying Application to Vercel
We will deploy our full stack application, including the front end and the GraphQL API endpoint, to Vercel. Vercel is a cloud deployment platform that focuses on the developer experience. It offers features like GitHub integrations, preview URLs for sharing live applications, and a CDN for publishing static content. We will connect our GitHub repository to Vercel, configure the project settings, set environment variables, and watch the project build. Once the deployment is complete, we will have URLs for the production version and each preview deployment. We will then discuss adding custom logic to our API. Let's go ahead and follow these steps to deploy our application to Vercel.
And to do that, let's go back to our slides. We're going to use Vercel. And to do that, I'm gonna use my Vercel tool to say I want to use Vercel. Vercel, I think of as like a cloud deployment platform for developers. So a big focus of Vercel is focusing on the developer experience. I don't wanna see that, I wanna see the landing page. So I think Vercel does a really nice job of focusing on the developer experience and basically giving us the ability to deploy applications with things like GitHub integrations. We get these really cool preview URLs. So we basically, any time we connect a deployment to a GitHub repository, any time there's a pull request, for example, or changes to that GitHub repository, we get a preview URL that we can see a full running version of that application actually hosted live to sort of share with our teammates and so on. So Vercel has a CDN that it publishes static content to. It works with serverless functions for API import, it just announced a new sort of edge handler functionality, which looks super neat. So I liked Vercel for deploying these kinds of full stack applications, and that's exactly what we are going to do. I think that's the only slide we have on Vercel. Oh, no, it's not. We have a few slides here. So what we wanna do now is take our GitHub, GitHub repository that we created from that template repo that's specific to you, what we're gonna do is deploy that to Vercel, so deploy our full stack application, the simple front end, as well as our GraphQL API endpoint. We're going to connect our GitHub repo to Vercel, deploy that so we can have that running, and then we're going to make some improvements to our application both on the front end and the back end, then we will see those update in Vercel. So we'll take advantage of that deployments preview functionality. If you have a Vercel account already, we're going to sign in and add a new GitHub project. If you don't have a Vercel account, you can just sign in with GitHub. There's a free tier, which is perfectly fine. You don't need to put in a credit card. So just like Neo4j Aura, we have a free tier to work with. Don't need to think about how much this is going to cost us, which is quite nice for development as well. So what we're going to do is sign into Vercel and click on new project. And if you sign in with GitHub, your GitHub account is linked automatically, I think. If you sign in with another method, you may need to link your GitHub. So when you sign into Vercel, I just use the GitHub authorization. So we'll click new project, and then we have the option of selecting what GitHub repository we want to import. It's usually sorted by which ones were updated most recently, which is quite nice. It also has some templates that we can clone, which is also cool just to get started directly. And then we'll see the screen to configure our project. There's a couple of things that we do need to configure here. Vercel does a pretty good job of detecting what framework we're using, but because we have our Next.js app in a directory rather than at the top level, we just need to point it to that directory, and I'll go through this in a minute, so don't worry about paying too much attention. So we do need to say what root directory we want, which in our case, it's called Next.js. And then we do need to set some environment variables. And these, we will, actually, I guess, because we have our.ENV file checked into GitHub just to make it easy. So we probably don't need to do this step, but in the real world, we wouldn't have our.ENV file checked into GitHub, so this is where we would specify those environment variables. And then we can watch the project build, and then when it's done, we will have a URL. We get a couple of URLs. One is URL for the project. So that's like the production version of the project, and we get a SSL certificate. So works with HTTPS and all that, which is very nice. But then each deployment, so remember, we had this idea of preview deployment, so we make a change from, say, like a pull request on GitHub. We don't necessarily want that to immediately be the production version, so the production domain may point to a different deployment, but we get a URL specific for this deployment as well that we can share with our team or whoever, if it's a client we wanna send something to before we push something to production, we get a separate URL that's specific to that deployment, which is pretty cool. Cool, so we're gonna do that, deploy it, and then we're gonna talk about adding custom logic to our API. But let's go ahead and I'll go ahead and go through these steps, and then we'll pause for a few minutes give everyone a chance to do that. So I'm gonna go to bristle.com, I'm already signed in, but I guess I'm done with GitHub so I'm gonna do a new project. And here are all of my GitHub repositories. I want this one I called GraphQL Galaxy full-stack workshop or something like that. Let me zoom in a bit, this is a bit bigger. So the project name, oh, this project name is not good. Let's change this to full stack GraphQL. And then this is going to be next.js. If I had the next.js app in the root, I wouldn't need to do that. It can detect it's the next.js app, but we have it in the next.js directory. So I need to click edit here to tell it I want to deploy this project to the next file. And then it's gonna say, you need to deploy this project just in the next.js directory. This means it's not gonna deploy anything that's not in that directory. The build and the output settings, these are fine. We can use the defaults, but we do need to set our environment variables. So neo4j user is going to be news graph. If we didn't have that AWSS issue and we all had our own private Neo4j Aura instances, we would have multiple Neo4j Aura instances, but we don't have that now, that's okay. So the user is news graph. And again, I don't think this part is actually technically required because we do have that.env file checked in, although it's env.locals. I'm curious if that actually gets read for a production deployment in Brazil. I guess we'll find out. I'm gonna go ahead and add these anyway. So neo4j user, we have neo4j password is also news graph. And then the neo4j URI is neo4j plus S colon slash slash news.graph.zone.
25. Neo4j Protocol and Secure Connection
The neo4j protocol, previously known as bolts, is now simplified to just neo4j. The plus S indicates a secure encrypted connection. If there is no SSL certificate, neo4j colon slash slash is used.
So this, the protocol neo4j plus S colon slash slash, this is neo4j is protocol for web data. Working with neo4j instances, the neo4j protocol since previously bolt, who's the binary protocol called bolts for sending data to and from neo4j. It's now called neo4j to sort of simplify the way of working with a cluster. When it was bolts, there was, if you wanted bolts routing or single instance, if you didn't have a cluster, now it's just neo4j, which is much easier to reason about. But the plus S means that we want a secure encrypted connection. So we have a certificate on this news.graph.zone, neo4j instance, and we want to make sure we use an encrypted connection. So that's what the plus S means. If we don't have a SSL certificate for our neo4j instance, we would just use neo4j colon slash slash. Like if we're using local instance, if we're using like neo4j desktop or something like that.
26. Adding Custom Logic with Cypher Schema Directive
We deploy our GraphQL and Next.js app, set environment variables, and use the Cypher schema directive to add custom logic to our GraphQL API. We can also implement custom resolvers but this requires more code and can result in nested requests. The Cypher directive allows us to add Cypher queries to our GraphQL schema, generating a single query sent to the database. The Cypher schema directive is available with the Neo4j GraphQL library and is one of several powerful directives. Field arguments defined in GraphQL type definitions are passed as Cypher parameters. This allows us to return computed fields and map nodes to types defined in the schema.
And then I think we also need to set the next public GraphQL. What do we call that, next public GraphQL URI. I think we called it that. Let's look in our ENV file. Next public GraphQL URI is slash API slash GraphQL. Okay, so I'm gonna add those environment variables and then hit deploy. And now Vercel is going to clone that repo, do an NPM build and the static content that it's generated is gonna go out to Vercel's CDN. The API endpoints, so we had, what we had slash hello, which was our very simple one and our GraphQL endpoint will be deployed as a serverless function. So we can take a look at the logs and watch that move along. Once this is done, then we will have a unique URL for our project.
If I go, while waiting for this, if I go to my team here to see all of my projects, there we go, here's sort of the status of this. I guess this is already done. Fullstack-graphQL.vercell.app. There we go. Welcome to Next.js. If I go to slash articles, I should see my bulleted list of articles. Yup, so that's coming from the GraphQL end point that is running at slash API slash GraphQL. Right here, cool. So we've deployed our GraphQL. We can do articles count just to make sure querying the same database. Yup, 4,500 articles. Cool, so we've deployed our Next.js app, both the backend GraphQL endpoints and the frontend as well, which is pretty neat. And, so I'll pause here for maybe another five minutes or so to give folks a chance to go through this. So sign into Vercel, create a new project, pull in the GitHub repo that you created from the template, set those environment variables, and basically just use what's in.env.local and then click deploy and you should see something like this. And if you go to whatever your domain is slash articles, you should see the list of articles. If you go to slash API slash GraphQL, you should see GraphQL Playground and you can write some GraphQL queries. So we'll pause on this slide, I guess, for five minutes and then we will move on to the final section which is going to be adding article recommendation. So we'll need to add some custom logic to our GraphQL API and then we'll need to take advantage of that functionality in the front end. Let's move on, in the interest of time here to talking about adding custom logic. So what we wanna do now is we have the basic query functionality for fetching articles but it would be nice if instead of just showing articles, the most recent articles, if we could say you know I'm reading an article and I would like to read other similar articles. So can I recommend similar articles based on the article you're currently looking at. So we wanna add that functionality both to the API and then also we wanna add that to the front end to fetch that data from the API and show that in the front end. But to do that first we need to talk a little bit about how we can add custom logic to our GraphQL API we'll use the Cypher schema directive which we mentioned a little bit earlier but we'll really take a deeper dive at looking at the power of that Cypher schema directive.
When we're using the neo4j GraphQL library there are basically two ways that we can add custom logic to our GraphQL API. We can do this using the Cypher GraphQL schema directive where we're annotating our GraphQL schema, adding custom logic basically by mapping a Cypher query to a field in our GraphQL schema. And when we do this, the benefit of this is that it takes care of a lot of like boiler plate code that we don't have to write, we're just adding a Cypher query to our GraphQL schema. Now, we're still generating a single Cypher query that is sent to the database even with our sort of custom logic query, our query is integrated as a sub query into that generated database query. And then another option for adding custom logic is implementing a customer resolver. So we can override the generated resolvers or we can define types that don't actually exist in the database and resolve those using custom resolvers. Downside of that is it's a bit more code that we have to write. We can do basically whatever we want in that resolver, we can query Neo4j, we can query another database system, whatever that is. Well, another downside is that we will call that resolver in a nested fashion. So first we'll send the query to the database, then we'll call this resolver which might result in another request to the database or to another data layer. So just important to be aware of the distinctions there. So let's look at this Cypher schema directive. So we said earlier that schema directives are GraphQL's built-in extension mechanism. Some indication that some custom logic should occur. Cypher is a schema directive available with the Neo4j GraphQL library. There are quite a few so far we've seen exclude, and relationship. Let's take a look in the docs at the other directives that are available. Here we go directives. So drop a link to this page in the chat. We can see we have quite a few directives available, things like for adding authorization rules, Cypher, which we're gonna use in a minute here, exclude, which we used. ID, which is nice for generating, auto generating IDs. The relationship directive we saw which we used to encode the relationship direction. So quite a few directives that are quite powerful. With Cypher, what we do is we add the Cypher directive and a Cypher statement. In this case, we're returning a scalar for a float field. So the example this comes from is looking at orders that may contain multiple books and we're calculating the sum of the price of those books to be the subtotal, so returning a float. Then, at query time to the client of this GraphQL API, it's not obvious that this is a computed field, this just shows up as another field in the API schema. We can also return nodes from our Cypher query that map to types that we've defined in the schema. So, here's a recommended field for a customer that's gonna return books they may be interested in based on books this user has ordered and other books ordered by users. Basically, what users are ordering the same books? What other books are those users ordering? Those might be good recommendations. But, note that we're returning, in this case, REC, which is booknets. And again, for users, for clients of our API, recommended just appears as another field, in this case, an object field. Any field arguments that we define in GraphQL and our type definitions for the field where we're using the cypher directive are passed to the cypher statement as cypher parameters. So here on this recommended field, we've added a limit argument, that's an integer with a default value of three. And whatever is passed by the user at query time, whatever value for limit that's passed as a cypher parameter here with this dollar sign limit syntax. That's how we refer to parameters in cypher.
27. Using Parameters and Projections in Cypher
We can use default values or required fields for parameters in cypher. Cypher queries can return projections of data that may not exist in the database, such as data from external APIs. APOC is a standard library for cypher that enables various operations, including querying external APIs and returning projections of data.
That's how we refer to parameters in cypher. I like to always use default values or make these required fields because that makes it easier to work with in cypher if you know that the value has been defined for that parameter. So here we're saying limit one, I only return one book. We can also return projections from these cypher queries to return data that may not actually exist in the database. So here in this example, we're calling out to another API using APOC load JSON which is APOC is like the standard library for cypher which allows us to do lots of things. In this case we're querying out to an external API and we're returning an object that matches the weather type that we're defined. So that weather type does not exist in the database but we're able to return a projection of that data.
28. Adding Similar Article Recommendations
We can use the cypher directive on query fields to create a full text index in the database for fuzzy matching. This can be used to search for book titles, even if misspelled. The same directive can be used on mutation fields for custom logic. We can write a recommendation query to find similar articles based on overlapping topics. By adding this query to the article type, we can display similar articles for each article. Let's start by going to Neo4j browser and writing the recommendation query. Then we'll add it to the GraphQL API and update the articles React components to render the similar articles.
We can use the cypher directive on query fields. So at the root level, one example that's might be nice is for full text index. So here we can create a full text index in the database that allows us to do fuzzy matching. So if we search for graph but we misspell it, we add this tilda, this is we've seen index, we've seen it as a text engine. This allows us to do fuzzy matching in the database.
Well, we can use that in a query field to search for book titles using this fuzzy matching full text index. So that when we're searching for books, even if we misspell it, we'll still get the results that we're looking for. Now we can also use this on mutation fields if we have some custom logic. We didn't really talk much about the mutations that are generated by the Neo4j GraphQL library. But if you want to create some specific mutations in addition to the ones generated for us, we can do that with cipher directives. For custom resolvers, basically the way this works is we add an ignore directive in our schema that tells the Neo4j GraphQL library that we are not going to try to fetch this data as part of the generated cipher query. You're basically saying that we are defining a resolver, we are responsible for fetching this data.
Okay, cool. Here is our last exercise. We have about 12 minutes left. So I think that should be just enough time. So, what we're going to do in this one, it says, use the article recommendation query from the first exercise to add a similar field on the article type. So we, because we had that issue with provisioning our oranges, we actually skipped the article recommendation query. That's okay, we'll do that. Basically what we wanted to do was write a cipher query that would recommend similar articles. So we'll do that, and then we'll take that cipher query and we're going to add that to a similar field on the article type. So now as we're resolving articles, we'll be able to see similar articles based on however we define that overlapping topics, overlapping organizations, we'll figure that out. But then we'll have that functionality, that custom logic in our GraphQL API, and then you'll need to update the articles React components to add that field to our data fetching and render that for the user. So for each article, you can see other recommended similar articles.
So let's start by going to Neo4j browser, do I have that open here? Here it is. And this is the news.graph.zone and username and password is just newsgraph, all lowercase, newsgraph, newsgraph, something like that. So how would we write a recommendation query? Well, let's start by just grabbing an article. Okay, so here's, we're saying match articles and then with allows us just kind of pipe things through or we can do aggregations or limiting, filtering. So we're gonna just spring through one article. So here's one article. And now I want to write a query to find similar articles. So if I'm reading this article, which, what is this about? Immunity cells in bone marrow, something about COVID, okay? So how would I find similar articles? Well, one way would be to look at the topics of this article. So what are the topics of this article? Let's make this a bit bigger. So coronavirus, vaccination, antibodies, immune system, science, bone marrow. We could also look at the organization, some Moderna, some NATURE article, and then a photo. Photo is not gonna be useful, photos are just specific for the article. So one way that I could define similarity would be, well, let's look at articles that are of similar topic. So you're reading this article about bone marrow, are there other articles about bone marrow? Oh, maybe you're all interested in this article about, what is this some disease that Colin Powell had that was in his bone marrow and had something to do with COVID. You may be interested in that. Well, we have a bunch of different topics though. So we don't wanna recommend just one, we wanna find the article that has the most number of overlapping topics and that's what we're gonna recommend. So how would we write that? Well, it looks something like this, match a and then traverse out has topic. And this is gonna be our topic node here. And then we wanna traverse out along the incoming has topic relationship to our recommended articles. So here's we basically follow this traversal from the article resolving to a topic, to another article that is the recommendation. But it's really like the candidate field for recommendations. So this can be kind of a two-step, one is get all of the candidate for recommendations, which are basically any articles with overlapping topics. And then we need to score those. So let's bring through the recommendations, and then we're going to do an aggregation. So we'll say count star as none. So what's going on here, Cypher has an implicit group by functionality built into it. If you're familiar with SQL and you have explicit group bys in SQL, where you can do aggregations grouped by some value, that's implicit in Cypher. So we use the with command, which we said is kind of like a pipe, allows us to do aggregations or limiting, ordering, those sorts of things. So here, this is kind of like saying, give me an implicit group by REC. So for each of these recommended articles, cause we're gonna have a whole bunch of these, right? Like we're gonna be a whole bunch of articles that have one or more topic nodes in common. I mean, if we double click on coronavirus, it was probably like 1000 or something, right? So we wanna score these by counting, we say count star, which is the number of paths that we've found for the specific article. So this is basically counting the number of overlapping topics from the article, the single article that we're resolving here to our candidate recommended article. So now num is the score essentially for our recommendations. So we can return the recommendations ordered by num in descending order and let's just like limited to 10. If we run that we get our 10 recommended articles. If we look at these, like at these in table view, so we have immune cells, COVID booster shots, scientific understanding variants. So these are all similar to the article that we're resolving, which was that something about bone marrow and vaccines. Okay, this looks pretty good. So let's copy this part of our query and go back to our code here. And I'm gonna go to my GraphQL API code and an article, I'm going to add, actually let's do this as a type extension. So I'm gonna say extend type article. This type extension just makes it easier to read so we don't have a bunch of fields cramped together. Typically you'd use this. If we had this part in another file, we can extend the types that exist in our schema. But I'm just gonna do it here for readability.
29. Enhancing Article Recommendations with GraphQL
We added the similar field to the article type and made it an object array field of articles. By using the Cypher schema directive, we generated a Cypher statement to retrieve 10 similar articles based on overlapping topics. We updated our deployment to include the new field and verified its presence in the GraphQL API. The next step is to use this field in the React component, which we'll leave as an exercise. We provided resources such as slides, code on GitHub, documentation, and the Neo4j Graph Academy for further learning. We also mentioned a talk at the GraphQL Galaxy Conference that delves into the concepts and benefits of building GraphQL APIs with the Neo4j GraphQL library. Despite the AWS DNS issue, we encourage everyone to explore Neo4j Aura and its provisioning of instances. Thank you for joining, and we look forward to seeing you next time.
So we'll say similar. This is going to be an object array field of articles. We're going to add the cypher schema directive, takes a single argument, which is a cypher statement. I'm just going to paste this in. And this is gonna be pretty similar to the query we wrote in browser, except we need to change A to this. So it was A because here we matched on a single article that we referenced under the A variable. Here, this is a special keyword that refers to the currently resolved article. This is going to give us 10 article recommendations. So we save that. That'll hot reload, we should be able to go to localhost 3000 slash API slash GraphQL. And now let's do articles, options, limit. Let's get 10 articles. And for each of these articles, I want the title, the topics. And now I have similar. Or we can also grab the title. Actually, let's not need topics. Let's make this a bit easier to read. So 10 articles, the title, and then for each one of those, give me similar articles and just the title. So here's what we end up with. So for the first article, immunity to coronavirus, here are 10 similar articles based on the number of overlapping topics. Here's one, another article, best time of day for exercise. And here's similar articles, low carb diet, cholesterol, exercising, exercising, fish oil. These are like health related articles. So this seems like a pretty good recommendation algorithm that we've got here. What am I going to do next is now I want to update my deployment. So I'm going to go to the terminal because right now I'm just running this locally. But I want to push this out for my teammates to see as well. So let's do a GET status, see we've made some changes here. Lets graphQL and we'll say, add similar field on article type. And we'll push that up to GitHub. So if I go to GitHub, I can see that I have updated that, let's go to my repositories. Yep, here it is, GraphQL galaxy full stack, graphql workshop. Add similar field and article type, here's the diff, just adding this pipe field here on the article. But if I go to Vercel, I should see that Vercel has picked that change up, and it is, oops, we just missed it in the log here if we go to our deployments. Here we go. So here's our first deployment, our initial commit, and then it, so Vercel automatically picked up this commit and did a build? And because we pushed to the main branch, it promoted that build to production. So now if you go to full-stack-graphql-vercell.app and we go to slash API slash GraphQL. And now if we look in the docs article, article now has a similar field. So because we pushed to the main branch, Vercel picked that up immediately and promoted it to production. If we had done a pull request, Vercel would have done a preview build and given us a deployment URL specific to the deployment. Would have been like this one, rather than just the cul-de-sac. And promoting it to production. Cool, so that's half the exercise. The next step is to now use this field in the react component. I'm gonna leave this one for an exercise for you at home since we're out of time here. It's been three hours already, but just to look at what we would do, we would go into pages articles.js and we would update this query to include similar title URL to add the similar field. And then now down here, as we are iterating through our articles array and rendering list items, linking to articles. Now for each article, we would then iterate through that similar because that similar field, that's gonna also be an array of articles, and we would do something like, say similar articles if you're interested in this or others may be interested in. But I'll leave that part for an exercise, for you at home since again, we are out of time. But thanks so much for joining today. I hope everyone enjoys GraphQL Galaxy Conference when that kicks off tomorrow or no, Thursday, it's on Thursday. Here's some resources. So the slides have all the contents for today. The code is also available on GitHub, I've linked to the docs. Also the landing page for the Neo4j GraphQL library has a good explanation of a lot of the different features and links to other resources. There is a self-consumable course focused just on the Neo4j GraphQL library that goes into a lot of the different features including authorization. So if you're interested in learning more about the Neo4j GraphQL library or other Neo4j courses, check out, it's called Neo4j Graph Academy. In the slides I did leave some sections from the other workshop we did on authorization because I think that's kind of the next step when you're building an application is, okay how do I sort of protect resources in my API. And there are some really cool authorization features built into the Neo4j GraphQL library. So I left those in the slides if you wanna click through or also we covered those in the training that we did last week. Have a talk at GraphQL Galaxy. I think it is on Thursday in the Milky Way track. Oh yeah, here it is at 10.15, 10.15 my time. So 10.15 mountain time. Putting the Graph in GraphQL with the Neo4j GraphQL library. So going into a lot of the concepts that we talked about today, but taking a look at some of the motivations and more specific features and some of the benefits that we have when we build GraphQL APIs with the Neo4j GraphQL library. Well great, we're over time. So we will leave it there, slides and all the code and that Neo4j instance we were running today is public and we'll stay out there. So feel free to use those as resources and do check out Neo4j Aura. Sorry, we had that AWS DNS issue that prevented us from using it, but those instances will provision once that DNS issue is resolved with AWS. It might be already, maybe not. Hopefully sometime later today that gets resolved. Anyway, thanks a lot for joining. I hope everyone enjoys the rest of the conference and we will see you next time.