Apollo React Hooks & Deploying To Neo4j Aura
Building A Real Estate Search App w/ GRANDstack Part 5
Picking up from building our GraphQL API, we update the React app using Apollo Client React Hooks and deploy our app to the cloud using Neo4j Aura and Netlify.
Links And Resources#
- Code on Github
- Apollo Client React hooks
- Neo4j Aura managed cloud service
- Neo4j Bloom graph visualization
- Hey folks, welcome to the neo4j Twitch stream. My name is Will. Starting in a little bit, behind schedule today. I had a minor issue to take care of but it should be okay to get started. So here's where we left off last time. So just a refresher This is now part five, I think of building our real estate search app with GRANDstack. We've been spending a lot of time working on data imports in neo4j and building out our GraphQL API, which is what the focus was last time. Focus last time we, let's take a look at the GitHub repo actually. So I'll drop that in the chat. I have a link there if you haven't seen that. So this is GRANDstack Willow in the data directory. This is where we have the scripts and queries to import the data. A couple sessions ago, we pulled down shapefiles on personal information, imported that into neo4j. First converting it to GeoJSON, and then using apoc loadJSON, uploaded at neo4j. Then in the last session, we took a look at this Python script to scrape the property records website that had a bit more information for each parcel that was not found in those shape files. So things like the neighborhood that the house is in, the size, the house, the size of the lot, number of bedrooms, bathrooms, that kind of thing. And that Python script created a couple of CSV files, which we then pulled in to neo4j, load CSV in Cypher. And then, so once we have the data in neo4j, then last time, we were using GraphQL architect in neo4j desktop. So GraphQL architect, this is, we'll call it graph app. It's a application that we install into neo4j desktop. In this case, it helps us build and query local GraphQL APIs. So let me drop the link, has the instructions to install graph architect, if you didn't see that last time, basically I'll just copy this link and paste it into neo4j desktop. Drop that in the chat. Okay, so that brings us up to speed on where we were last time. Today, I want to, I guess first of all finish off where we were with with GraphQL architect with our GraphQL API, and see how we can export this GraphQL API that we built to our GRANDstack starter, which is the project that we started from back in the first session, so we were using the Create GRANDstack app to build out the skeleton of our application. And then we deployed that using Netlify and neo4j sandbox in the first session. Now what I want to do is show how we can go from having a GraphQL API that we've built with GraphQL Architect, export that to our GRANDstack starter project. And then I want to, we've been ignoring the front end a bit. So I want to spend some time updating the skeleton project that we have in GRANDstack starter, which is this kind of dashboard application for business reviews. So we'll change that to work with our real estate data model. And then I've had some folks ask about, how do we deploy this to a real neo4j instance in the cloud somewhere? The first session we did neo4j sandbox, which is great for kind of developments, but what do we do for a more long term running solution? So I think we'll take a look at how to deploy to neo4j Aurax if you're not familiar with neo4j Aura This is neo4j database as a service. So it allows me to spin up neo4j instances in the cloud. I can scale those up and down, it gives me a cluster relations more than just a single instance. So today, we'll try to get our app up and running on neo4j Aurax and Netlify after we make some updates to the front end. And then I want to take a look at adding a map components to our application. Cool, so let's get started. Okay, so this is where we left off last time. So in GraphQL, architect, we had created the GraphQL type definitions for our API. So here I just clicked on start local server. And here's the the GraphQL query we were running at the end of last time, let's bring that down so you can read that better. So in this case, we're searching for properties using some of the built in filtering that we have, I'm gonna make that a bit bigger, easier to read, yeah, let's (murmurs) a bit. So we're using some of the built in filtering that we have in the neo4j GraphQL JS library, which is the library that powers so that's sitting underneath GraphQL architect which is powering the the GraphQL API that we're running. And specifically, we wanna look at the documentation for this GRANDstack.io. This is a site that has the documentation for neo4j GraphQL JS, and specifically, we're interested in the filtering functionality. I'll drop a link to that in the chat. Okay, so we're taking advantage of this filtering to search for, properties that have more than four bedrooms, more than three bathrooms. So this is bedrooms_gt for greater than, we can also do less than or equal to, and so on. And then we have a specific point. This was latitude and longitude for Montana State University. So we're searching for houses within one kilometer at this point that meet these criteria, and then getting some details about them. Cool, so now we want to deploy or export this GraphQL API project to what we were working with in GRANDstack starter, so the GRANDstack starter project that we created last time. And again, this was done using the Create GRANDstack app. COI. So Create GRANDstack app. That is what we used to create the skeleton application that has both the code for our API. And so far, so I think we could use the infer schema functionality in the GRANDstack starter at some point. And we had this version of a very simple GraphQL API in schema.graphql. If we look at at index.js, what's going on here, so this is index.js for our API application. So this is our node.js GraphQL server. What it's doing is it's pulling in that GraphQL schema. Here are the type defs that are defined in schema.graphql. It's pulling those in. It's using make admitted schema from this neo4j GraphQL JS library to create a GraphQL server using Apollo server, and then serves that localhost 4001. So we want to do is, how do we export these type definitions to our GRANDstack starter project? One thing we can do. Let's do cd api source. So this is where our schema GraphQL file lives, we take this location. One thing we can do in GraphQL architect is export the schema. So if we look at our deploy options, these are a bit of work in progress. GraphQL architect is still fairly new. And I think we can explore some other export and deploy functionality for now. What we can do is export this schema.graphql file into our GRANDstack starter projects that we have locally. I'd be curious to know what other deployment options folks would be interested in. We're thinking of things like GitHub integration, maybe deploying, specifically integrated with Netlify, maybe versal, maybe EDOSlambda, those sorts of things. But anyway, chime in the chat or the comments, or feel free to ping me directly if you have thoughts on what sort of deployment integration you'd like to see in GraphQL architect. Anyway, for now, we're just going to write this file to our GRANDstack starter project. So I'm gonna stop the local GraphQL server that's running in GraphQL architect, switch over to my GRANDstack starter project. Look at my schema.graphqL file. And Yep, it's been updated with the definitions we created last time in GraphQL architect. Cool. So I can run the NPM run start to spin up both the GraphQL API and the dev React web server. But before I do that, I wanna take a look back at at index.js code for my GraphQL API. So first let's tweak a couple things here. So we call the makeAugmentedSchema. In, in the version that we started, if you remember, back to the first session where we had a schema of business reviews, and users and ratings, we had this sort of computed type that we were excluding from the auto generated GraphQL API for makeAugmntedSchema. So we don't have a rating count. Yet, that's fine. We can we can leave that in there I don't think that'll cause us any problems. The other thing I wanna look at is the initialized database step. So this runs initialize.js and calls apoc.schema.assert and passes in what looks like some sort of configuration for setting constraints based on our old schema. So what is this doing? Let's take a look at the docs here, apoc.schema.assert. So apoc we've said is the standard library for neo4j. It includes a bunch of helper functions and procedures, and schema.assert is one of them. That drops all other existing indexes and constraints. If this drop existing flag is true, the default is true. And asserts that the end of the operation to given indexes and unique constraints exist in the database. Cool. So it takes two objects. The first one is index labels and index keys. So for any indexes we wanna create. And then the second one is constraint label and constraint keys. So for any existence, or uniqueness constraints rather that we want to create. So if we look at, let me closeout of GraphQL architect, I think we're done with that for now and switch to neo4j browser. You're gonna do a colon schema to see the indexes and constraints that we created. Some of these we created last time, but some of them if you remember, every time I opened up my database, I had these new business review constraints. So we're wondering where those came from. So this is where they come from because I had started our GraphQL API that went through the initialization phase, it was creating these old constraints, which I don't want anymore. So let's update this before we start the API again. We want, let's see business we don't care about, category we don't care about. Neighborhood. Neighborhood name is unique. So instead of user capital N, neighborhood, let's just name property ID is unique. So instead of business, we'll say property ID and then instead of review we don't care about, subdivision we do care about. Subdivision has main D subdivision, name and then category we don't care about. So let's just delete that, since we don't have a category in this data. Okay, so this second object that we're passing, is with the constraints that we're creating. The first one is in the indexes. I want to create and index on the location property. So let's jump back to neo4j browser, match P property. So get the first 10 of these LB cattle Co. Okay, so this property node has a location, that's a latitude and longitude. And because we're using that in the filter, I wanna create an index, a spatial index. So then this is using an index to find these efficiently. So we'll create that here, property location, which will create an index on the location property on our property notes. Okay, so save that. And let's see out to the root of our project. And if we do an NPM, run, start. Let's see what happens here. And so this should start both the development React web server, which this has opened, automatically, localhost 3000. So that's building our React app. And then it says our GraphQL API is ready at localhost4001/graphql. Let's check that out. So here's GraphQL playground, which allows us to write some queries we can check out the docs tab, city subdivision, neighborhood, property. Cool. Let's write a simple query that says show me all the cities. Great, got some cities. Let's check next our .emv file to make sure we're connected to the right database. So yep localhost 7687, which is the default for a locally running database which is this one in your desktop. Previously, we had connected this, I think to a sandbox instance that went away. So that's the right connection credentials in this .emv file, which is what's used by the GraphQL API to connect to neo4j using the neo4j JavaScript driver. That's exactly where those are being used. It's using this .emv library to set those as environment variables. And then here when we're constructing the driver instance, we're using those environment variables we have fall back to the defaults. Okay, so let's check out the React application. So if you remember, the first time we ran this when we had the sample data, and our business review schema, we had kind of this dashboard view that was showing us, it had like a chart of the distribution of stars of the reviews, I guess here and it had like the number of users in the database, a simple count here. And then here it had a table of business review. So kind of a dashboard view. But, of course, we're getting errors, because we have changed the GraphQL schema that the React app is trying to query. If we open JavaScript console, and go to network, let's do a refresh. Just the XHR network request, which our GraphQL requests, we can see we're making three GraphQL requests. And once we get a 400, bad request and see the query that we're running. So query we're running is here. So ratings count, then bringing back stars and count and type name. And if you look in the response, the message is cannot query field ratings count on type query. So these are the three GraphQL queries. Each one of these components individually is ascending. So let's jump into the code. Look at that. So in the Web React directory, we've got source. Then if we look at app.js. So there's some styles here and kind of the boilerplate things that are handling kinda like this drawer sliding open and some things like that the the toolbar up here with our logo. But if we look here for sort of the main content of this components, we're using a React router and a switch. So when the path is just the route, we load the dashboard component, and it's slash business or slash users, we load this user list component, so here at the root, this here in the middle is the dashboard component. We just click here, we switch to slash users and using React router we're loading this user list component we're just also airing because it is using a different GraphQL query than what we have in the API. Okay, so we're interested in components dashboard. And if we look at dashboard, it has some styling, has sort of a grid setup. So this grid is what gets us we look at that, what's going on here. So this is the standard 12 column grid setup. So this gives us a nice, responsive feel. So if we go to insert an extra small, then we take up 12 columns, so it's extra small, we take up 12 columns, if we're in the standard width then this first one is taking up, what? Seven columns. This one, which is our user count gets five. And this one always gets 12, so it always gets its own row. Okay, so that's the grid layout. And then we're letting the ratings charts components. So that's here, ratings charts, user count component here. And then recent reviews, which is this table here. So the most simple one of these is the user count. So let's let's start there. So back in components, user account. So what's going on here? We're pulling in this use query, apollo React hook, which is how we're fetching our data. We're also pulling in typography styles titles from material UI, so we'll talk a bit more, maybe in the next session about material UI, and then how we do some of the styling and what components are available there. But for now, what I want to focus on is the data fetching. So we're also pulling in the GQL tag, which allows us to define GraphQL queries. What this is doing. So here we're defining a get count GraphQL query. What the GQL tag does, it parses the string here in the template string into an AST or abstract syntax tree, which is what the representation that we use of the query when we send that with Apollo client. What's nice about that is in the editor, we get syntax highlighting and whatnot. There's there's other integrations we can use to connect this to running GraphQL APIs so we can actually see in our editor if we have for instance, a type that doesn't exist. And so when there's lots of nice developer tooling we can connect that up to. But the basic gist here is, first we define our query, wrap that in the GQL tag, then we have the functional React component. We call this used query hook, parsing in the GET_COUNT_QUERY, which is just a really simple GraphQL query that's just calling the user count field on the query type which is expecting to get back a single value. And we get back loading air data objects from our hook here. Then when we render, first we say okay, is there an error, so if our GraphQL query returns an error, then we don't want to bother with any of this just return a paragraph tag that says error. That's what's happening. Remember, because we saw that error in the JavaScript console is says, "Hey, this this GraphQL query "does not match the schema of the GraphQL API "that's running." So we just return a single error in the UI. If there wasn't an error, then we would return total users, we'd use the typography from material UI to give us nice looking content. Then we check to see okay, are we loading? So this GraphQL query goes through a few different states First, it goes through a loading state where we maybe have sent the query we didn't get back an error yet, but you didn't get back any data. So in that case, say hey, this query is still running, it's loading. If it's not loading, if it's not an error, then we should have a user count value in this data object. And then in that case, then we can render again, wrapped in this typography for some styling here. But here's where we're getting out the actual value and rendering that in our component. And of course, we don't have a user count. So let's go back to our schema. And what we wanna do so if we take a look here, these are the types we've defined, what we need to do is now define a query type. So this is sort of extending the auto generated query type that the makeAugmentedSchema function gives us for free and let's create a property count field, that's going to be an integer. And we're gonna use the Cypher schema directive to define some custom logic here. So we've talked about this a couple times. But let's take a look in the docs, Cypher schema directive. So when we're defining our type definitions, we can add this GraphQL, or this Cypher GraphQL schema directive that has a Cypher statement. That gives us some custom logic sort of like defining a computed field. Let's drop that in the chat. And that's exactly what we wanna do here. We wanna say, let's match on all the property nodes and just return the count, we're gonna save and that should pick up that there's a change in our schema. If we go in GraphQL playground, let's try to run that. Property count. 49,504. Cool. Okay, so now that's in the API. If we go back to our user count component, instead of user count query, we want to run property count. And instead of data.userCount, we want to grab data.propertyCount. And instead of number of users found, we'll say property's found. Okay, so it'll rebuild our React application. And if we jump back, cool, it's now this load. So total users, let's change that to total properties. Cool. Found 49,504 properties cool. Okay, so that was a fairly simple one. Simple component to update our data fetching, the next one we wanna do, let's do this chart. So this was ratings chart. And this has a similar setup, we import some styles from, components rather from material UI. We're again using the use query, React hook, we're importing some things from the rich arts library to create a bar chart here. So we're running a query ratings count, getting stars and count. So this gives us a list of star count pairs. So what we're getting before was sort of the histogram. So for the number of stars like one, two, three or four, we're getting the count. So there's 10 reviews that have five stars, that kind of thing. And then passing that to our chart component. So in this case, we're gonna need to define another custom field on the query type. So for our chart, let's show maybe for each city the average value, the average appraised value or something like that, for each city, which we can define in a Cypher query. So let's call this city values maybe. And what's it gonna return? It's gonna return a list of, we'll call it city values. So this type, we haven't defined yet. And it's gonna be kind of a computed type. What is it gonna be? Let's have those type city value is gonna have a city, it's gonna be a string, so the name of the city and then, let's call the other field average, which is gonna be a float. And that's gonna be the average property value of all properties in that city. So we just need to define a Cypher query that's gonna return the data for this list of objects. So we're gonna do sort of an aggregation for all properties in each city. So that will look like, let's break this out into multi line. There we go. So we're gonna lose our syntax highlighting, but I assure you this is valid GraphQL SDL syntax with the triple double quotes for multi line, string arguments. Okay, so what's our Cypher query? It's gonna be match on all the cities that have a property so every property that's in a city and let's filter out only properties that have a total value. So this is every property has an assessment, an assessed value. The county says your property is worth this much money. And that's what this value is. And then what we wanna do is for every city, calculate the average p.TotalValue, that's average. So this will give us kind of a group by city aggregation calculating average total value for each property in that city. And then what are we gonna return? We need to return something that matches this structure. So we'll return an object that is composed of city with the key and city, there's this value and the same for average and give it a name, I'm gonna call it object. Okay, there we go. Got our syntax highlighting back. So what was the problem there? Oh, it wasn't on a new line. Okay, run a new line. Then VS code can handle the triple double quotes for multi line string arguments, cool. Okay, so let's see if that works. So we'll jump back to GraphQL playgrounds, set of property counts. What did we call that? City values. Where we have city name and average value? Cool, looks like that works. Get a bunch of cities and then the average value of properties per city. Great. Let's jump back to our ratings chart component. And we wanna do, let's just copy this query, city values. And then in our React component, so we're using the use query Hook. We are instead of ratings distribution, let's say average city property value. And then we're using the bar chart component from this rich arts library. So the data is not gonna be data.ratingsCount. It's going to be data.cityValues. And then for the x axis, which I think back to high school math goes that way. On the x axis, what do we want? We probably want the city label, that looks fine. Let's change the name of the label to city and then for the y axis that is going to be what did we call it? Value average. Okay, so we'll save that. And let's see what that looks like. Cool. There's our chart. So West Yellowstone is significantly skewed here with average value of 3.2 million. Big Sky looks like it's number two with average value. 900,000 or something? Okay, cool. So there's our chart. The next thing we're missing is this table, in the table so previously we were showing business reviews. This time let's show some property listings and we'll show like the address and then some attributes about the property. So that is going to be our recent reviews component. Okay, so here's the query we're running before, where we're looking at the most recent reviews. Let's jump to GraphQL playground to write our updated query, make that a little bigger so that's easier to read. So what would make sense here, instead of recent about so we don't really have a time component here. Maybe let's just show like the most expensive, maybe that's interesting. So let's look at the first 10. Order by total value descending and address and total value. Some of these are missing an address. So our table doesn't look wonky. Let's add a filter. So we'll say filter where address is not, no will that work? Yes. There we go. Okay, so these are the 10 most expensive assessed properties in our database that have an address. What else would be interesting, other than the number of bathrooms, number of full bath and a half bath. And if they're in a subdivision. They don't have the name for the subdivision. Okay, well none of these are in a subdivision. That's not very interesting. Let's, maybe add another filter here. Let's bring this down to something more readable. So we're filtering where the address is not null. And then we're gonna say in subdivision where the name is not in a. There we go, that works. Some of these we don't have bedrooms, full baths or half baths. So let's just add filters for all of those, like bedrooms. Not null and full baths. So just adding some filters here just so that we make sure that our table looks nice. Okay, so that should be enough to show in our list. So most expensive properties where we have enough information to render a table. Okay, cool. So we have the GraphQL query, so that runs but if we look at our React app, we are still throwing an error because we're trying to pull out data that doesn't exist here, so we don't have a business and user and so on. So what do we want the headers for our table to be? Let's call these most expensive properties. And I think here's our error in our React app we're calling map where we don't actually have reviews. Okay, so what do we wanna show? Let's show the address, the subdivision name, the number of bedrooms. And actually what would be more be more interesting I think is I think the square footage of the house maybe that's a bit more interesting. Yeah, there we go. You can see we have, we can see that our scraper was probably not great in some aspects. I'm sure there are some cases here where we grabbed maybe the square footage of the garage or something. Not sure what was going on there. Anyway, because we have a 800 square foot house, it's one of the most expensive, doesn't quite make sense. But anyway we have value, that's fine. We can revisit our scraper later. So bedrooms, square feet, and then total value. Okay, cool. So if we look at our query. So this is gonna render the header for the table. And then we want to iterate over property. So looking at our GraphQL query, data.property is gonna be an array with these values in them. So the ID, oh yeah, so every row needs a unique key, which we have that is the property ID. So we'll bring that back too. So we'll say row.id. Row. Second one is the subdivision name. So this is gonna be row in subdivision name that matches a query here. I think we could've said dot. in subdivision. Okay, and the second one is the number of bedrooms, that's just gonna be row.bedrooms and square footage. We're just gonna edit this one, the first first one is the address, not the subdivision. So let's copy this row. This is gonna be row.address, square foot and then total value. Whatever extra row there and let's see if this works. Cool. Looks like it mostly worked. So we have address, bedrooms, we're missing square feet and subdivision name. What happened there? Oh, a square foot, we don't have because we didn't include that in the query. There we go. There's square footage. And subdivision name. We don't have. Where are we gonna set that through? Dot. I think spelled it wrong, in subdivision. (murmurs) Nope. Okay. Let's do a... So instead of rendering our table, let's do log.data. So for some reason, we weren't getting subdivision if we jump to the console. All right so in subdivisions. So we're saying in subdivision.name, but in subdivision is an array of subdivision objects, which we can see here. So let's fix that. So row.insubdivision. Let's just grab the first one. So, index zero, the subdivisions and then call name on that one. There we go. Okay, cool. So now we have queried our GraphQL API using Apollo client React hooks to populate our dashboard components. That is using our new neo4j GraphQL JS library to generate Cypher queries from GraphQL. And sending that to our local database to fetch data to populate our application. That's, good. But we want to deploy our database now somewhere to the cloud. So I could push this out to Netlify right now, and that would be fine for the front- ends and for running our serverless GraphQL API that we set up last time in the first session. We set that up on Netlify using net LIFFE I functions, but they can't query my local database on my machine. If you're looking at that from homes that's not very interesting. So what we wanna do now, let's see how we can deploy this database piece of this I should say to neo4j Aura. So we'll create an Aurax instance, cluster rather, I should say, create an Aura cluster. We'll push up our local database to Aurax. And then we'll deploy our updates to Netlify both to the React front end and the GraphQL API. And we'll have that querying our Aura neo4j instance instead of the sandbox or my local database. So I'm gonna log into Aurax, I already have an account so we'll click Login. And we'll sign into Aura I've already signed in so I didn't go through the auth flow, though. Let's just go ahead and create a database. We're gonna call this about Willow GRANDstack and choose a region. Sure US central one is fine, you can scale this up. This doesn't need to be a massive database, just a two gig is probably fine. Could probably just get away with a one gig. Okay, here's my credentials. let's paste these somewhere. Yes, stored my credentials. Okay, so this is spinning up, so I'll change the password later. So don't worry about that. Let's take a look, while this is spinning up at some of the other features that we have in Aurax. So in this import tab, this is something we're going to need to think about. How do we import data into Aurax? We have all of those, those load Cypher scripts that we ran last time, which we could run, that would be fine. The only thing that is a little bit problematic is we have like the, the geo JSON files and the CSV file. So we'd have to put those in like an S3 bucket or somewhere that Aura could reach over the network if we wanted to do that. Instead, what we can do is push up an already existing database. So there's some tooling that allows us to do that from neo4j desktop. So this is kind of a wizard that walks us through the process of using the command line tooling to do that, which I'm sure is perfectly fine. But instead, what I wanna do is use another graph app. So I'm gonna go to install.graphapp.io. If you haven't seen this, this is the graph app gallery, paste the link in the chat there. So previously, we were looking at GraphQL architect, which is this graph app that allows us to build GraphQL APIs using neo4j desktop. And that was cool. There's a whole universe of these graph apps that do lots of other things. Things like the ETL tool for importing data from relational databases, Heylin, which allows us to monitor our cluster, things like Neuler, or the graph data science playground, which allows us to use the graph Data Science Library with a nice UI and then some data visualization in there. So there's all kinds of graph apps. I'm interested in this one, the neo4j cloud tool. So this is a graph app that has some nice UI functionality. for working with neo4j Aura. I can install this either just by clicking this link, which is a deep link into neo4j desktop. Or in this case, what I want, oops, is to just copy that URL. And if I go into neo4j desktop, this was already selected, but the way we get there is clicking on this graph applications sidebar and pasting that install URL there, which will install the neo4j cloud graph app. So while that's installing, let's jump back to Aurax. Okay, so we were looking at import, there's also the connect tab. So the connect tab is nice because it shows us we can choose our different databases here and it will populate the Connection Credentials in these scripts here. So how do you use the various drivers? For neo4j, there's a GraphQL example that shows us how to spin up a GraphQL API that connects to our Aurax instance. What else? We have documentation for Aura and then the feedback portal. The feedback portal, if we look at feature requests, this is a good one. So if there's some features in Aura that you're interested in that you're not seeing, definitely take a look here in the features requests forum for Aura. This is great. It's great for knowing, from users, what features would you like to see that you're not seeing on Aurax and then we can also give you some indications of what's going on. For example, the top rated one is neo4j 4.x on Aura. And this is in progress, this something that's being actively worked on. Okay, cool. So that is the general functionality for Aura. While this is running, we're still waiting for our Willow database to spin up. Let's take a look at the database dashboard. So this is for an Aura database that I have that's already running. And this one, I think, does not get very many active requests, but what sort of information can we see in the dashboard, so we have lots of metrics, both how many queries are coming to the database, CPU usage. That's sort of thing. If we want to, we can just sort of drag and dump file from your desktop or from some other database. So dump file, it's kind of an exports of neo4j. So this is another easy way to just upload some data. We have our same code snippets here, we have the ability to export and restore backups. So that's really nice. And then we can scale our database as well. Okay, cool. So while this is spinning up, let's refresh let's just make sure that didn't spin up while I wasn't looking. Still going out, so back to neo4j desktop. says yes, yes, I do want to install the neo4j cloud tool. Let's go ahead and fire up the neo4j cloud tool. So this graph app is gonna walk us through the process of uploading a database that we have installed in neo4j desktop into Aurax. Let's start that again. There we go. So it's gonna walk us through the process for uploading a database that we have in desktop to Aura. Why would we want to use this instead of I saw in the console for Aura that I could just drag in a dump file there. Why wouldn't I just do that? What's nice about the graph app, because we don't have to go through the process of creating our own dump file. Instead that happens automatically with the graph app. So this graph app is saying, "Hey, you need to have an active connection "in neo4j desktop to an Aura database, "but you're currently connected to a local instance." So here's how you create an Aura remote connections. So if we jump back to desktop, so currently I have, this is the willow GRANDstack project. And in here, I can have multiple database instances, DBMS instances. Right now I have one Willow GRANDstack, I'm gonna create a new one. And instead of a local graph, I want to connect to a remote graph and this is going to be my let's call this Willow Aura. This is gonna be my Aura instance. And I need the connect URL for my Aura instance which is here. So this is now done running. Since I'm not running done spinning up, and the database is up and running. So paste in our connection credentials there, username and password, the default is neo4j and then let me grab where I had pasted that password before. Hopefully no one was super fast and went in there and changed the password when I wasn't looking. Okay, so now what we have is a remote connection to a database knotx that's running within neo4j desktop and now running in Aura. And if we go back and then we need to connect. So in desktop we have one active database at a time. And this is nice because what it means is that for any of the Graph apps that we're running, if it's like neo4j browser, if it's bloom, if it's GraphQL architect, any of those graph apps, It knows the currently running database, whether it's a remote database or local database. So we're gonna activate our Willow Aura connection. And then switch back to the neo4j cloud app. And now instead of giving me an error, it says, "Hey, is this the remote or a database you wanna use?" Yes, it is check for existing databases. So because we're uploading a new database, It just wants to make sure that the database is empty or give us a warning that says, "Hey, there's some data in here." That's not cool. So now we need to select a project. We're interested in the Willow GRANDstack project in the database is this one. So let's go ahead and import that. It asked me if it wanted to run some backgrounds process I said yes. So what is it doing now? So now this is creating the database dump. So this is creating the export from our Willow GRANDstack database. And then it's going to use those command line tools that we saw here. So we're starting to use this neo4j admin push to cloud. Basically what the graph app is doing is running these command line tools behind the scenes so that we don't have to worry about it. Okay, so any questions so far? Feel free to fire away in the chat if anyone has any questions or feedback. While this is running, this will take I think a bit to upload and restart the database. Let's talk about what we want to do for the next bit of the UI in our application. So here's what we have so far, we have this dashboard, where we have kind of a chart, a very, very simple React app. It's just giving us a count of properties and then listing some properties and their attributes. So what I wanna do next is now start to think about the functionality of our real estate application. So if we go back to GitHub, and if we look in our ReadMe, I think the new GitHub design doesn't like my hidden arrows mark up here in ReadMe. Anyway. Okay, so we had started to sort of list out some of our requirements for the application. So we know that we want to allow users to search for properties by city and view details. We know we want the user to be able to use use the filters to say, "Hey, I want a house "that's at least these many square feet, "has at least this many bedrooms and so on." View it on a map. We know we want to be able to draw bounds on the map, so let's take a look at how Zillow does this. So if you look at Zillow, the data we have is for Bozeman, for sale. Let's remove boundary. So it's showing us this boundary is the boundary for the city of Bozeman we have good data for Gallatin county which is a bit bigger than that but in our map, we wanna be able to have a map view where we're sort of scrolling around on the map. And we see properties sort of pop up, we can view details about the property when we click on it. Look at photos, scroll through and look at attributes of the property. So the map has to, kind of be hooked into our search functionality or GraphQL API. So we need to have some way to search for properties that are within the bounds of the map, So that's one thing that we need to do. But then also, we need to be able to handle searches for properties within a polygon so we can draw on the map. So maybe I want properties that are on this side of the mountains and I don't know maybe like this neighborhood that's sort of on the North East side of the streets, maybe, so I can draw some arbitrary polygon. And now I'm only showing properties that are within that arbitrary polygon boundary that someone Drew. So anyway, so these are the functionality that we need to be able to work with in our map component. Last time, we saw how to do this, essentially from the API side, so we saw how to use the the radius distance for filtering property searches in our GraphQL API. That we kinda get for free just by having that location property in there. And we saw how to, we were doing point in polygon which is very similar to the type of search we want here. So we know we can use that spatial algorithms library to do this sort of polygon search. So we know we can do it from the API side, we need to think about is how to do it from the UI side of this. So what I wanna do next is add a map components to our React application. Okay, so that was a little bit of a detour on the functionality that we're looking for. Let's check in with our import, it says import succeeded. We jump back to Aura. Cool. We can open up with browser or with bloom. Let's go on a little bloom detour. So if you're not familiar with bloom. Bloom is a graph data visualization and graph exploration tool. Let's hide my password again, like this. No, I don't want to save it. Yes, so bloom is this graph visualization tool that lets us interact with your neo4j databases visually. Let's do a new scene. Cool. So bloom allows us to visually and interactively explore the graph which is neat. First Blum generates a perspective from our data. So this allows us to configure what and how the data is shown to us visually. So we can exclude any of these properties from being shown. And this is nice. from a security perspective, you wanna say, certain users have access to this perspective, which excludes maybe the name of the owner, the address of the property. And we wanna give grant that to users with limited access or something like that. We can choose the caption, it's address. You can also, what else do, oh, we can also choose icons, so we go in the styling here. Let's toggle off our our rule based styling. We'll talk about that in a second. Let's set an icon. This is a property so you have any house icons. Oh we have many house icons great. How about this one looks fine. So how do we use bloom? So we can use this sort of natural language search functionality. So let's search for property where the number of bedrooms is I know nine, if we even have any houses with that many bedrooms with ginormous, hey we do have a few, cool, Okay so then we can like click on one of these and get some details. So this is rocking horse drive and Bozeman. can then do interactive expansions. So if we wanna say, "Okay what city notice have in." Yep, it's in Bozeman. Let's just expand all relationships. We can see that it's in this neighborhood let's expand out from this neighborhood notice here all of the other properties that are in this neighborhood and there are a lot, there are like 3000 of them. Another thing that we can do that's nice is let's close that property card there. A thing we can do that's nice is we can configure the styling to be based on values of properties on the node or relationship. So, if we could jump back here, to our rule based styling, for property nodes, we can instead of single if we go to range so these are now property based styles on total value, let's do a size, let's change the size of the node depending on the value of the property. If the value is high, we'll make the node bigger. And then let's value's low, let's make it smaller. And this is useful for things like when we wanna do when we're running some of the graph data science and graph algorithms, so if we run say like PageRank, and we wanna see the most important nodes in the network, we want those to be bigger. If we're running like a community detection algorithm, we want nodes in the same group to be the same color and so on, but useful for at a glance, we can see sort of here's a property that's assessed value is a lot lower than say like this one. Okay, so that's Bloom. Bloom comes with neo4j Aura. It's also included in neo4j desktops. We could have done this neo4j desktop, as well. But I got excited when I saw it in the drop down there. So okay, little detour from Bloom. Let's go back to neo4j browser. For our Aura instance. I guess we don't really need to look at our data in neo4j browser. We looked at it in bloom, we confirmed that the data was there. So that should be good. Instead, let's deploy. Now our application, both the React app and the GraphQL API to Netlify, I guess maybe let's just test it locally first and see how we can do that. So jump back to Visual Studio code. Let's take a look at our .emv file. So here we're specifying which database for a GraphQL API to connect to. And in this case, I want to connect to this Aura instance. You'll see my password again, briefly. But that's okay. We'll change that later. Here's our password. And then I'm gonna uncomment this neo4j encrypted equals true line because I wanna use a encrypted connection with Aura and I need to restart my server because I don't think that gets picked up by the watcher. I changed that .emv file. Okay, so if this works, we shouldn't see any changes when this once reloads, we should actually just see the same view of this dashboard that we had when we were running this locally. But now, it should hopefully connect to our Aura instance. So I'll wait for this to compile the React build. I think so while we're waiting for that, okay now it's done. Let's reload that. And their data our data comes in. Cool. So that is our locally running React application hitting our locally running GraphQL API. But now instead of the GraphQL API talking to our local neo4j instance, it's talking to our neo4j Aura instance. So now we can deploy our React app and our GraphQL API to Netlify, which will then talk to talk to Aura. So let's do that. So first of all, we set this up on Netlify previously, let's just jump into nullify and change the database that we wanna connect to. So it should already be signed into nullify. Let's see if we can remember which project this is. It's not this one, not this one. Might be this one. Deploys from GitHub. Let's see which, yes, it's gonna do well with GRANDstack. Cool. So the first thing I wanna do, so this is hooked up to our Willow GRANDstack GitHub repo. We did that when we first set this up. If you wanna see how to how to connect that, I think we did in the first session. So that is up and running. It's basically Netlify is just waiting for any changes to come through in GitHub. And then it will build and deploy based on those updates. But the first thing we need to do is change the credentials for the neo4j database that our GraphQL API is gonna talk to, and that I believe is going to be in the deploy environment variables. So here, these are the environment variables for our neo4j sandbox instance, which I'm sure has since expired, so let's change these. Oops, so here's our password for the Aura instance. Do I go back to Aura, copy the credentials neo4j user, here's neo4j and then I need to add a new variable, which remember we uncommented that line in the .emv file, which is setting neo4j encrypted. Is that what it was called? I think so. Neo4j_encrypted. Okay. Cool. So we've updated those values for the environment variables for our build for Netlify. So now we just need to commit our changes. And when we push those changes to Netlify, it should build using those new values for our environment variables. So we have some untracked files here in the data directory. This is the shape files and some of the CSVs that we build. So I don't wanna check those in but I do want to, let's look at what we changed. We changed API source initialize, API source, schema.graphql. Those are the changes we made to our GraphQL API. And then we changed components, each one of our components, the ratings, charts, the recent reviews, and the user count. Let's commit and we'll say updates for property data model. Something like that. That'll run prettier, make sure my codes formatted correctly. push that up to master. Okay, so that is pushed to GitHub, we can verify that. If we take a look at GitHub, and look at the commits, updates for property data model 29 seconds ago, cool. Now, if we go to nullify, and click on deploy, as you can see that we have a deploy that is building, and you can sort of watch this run. So if you remember what this is gonna do, let's take a look at our build configuration here, which is just in the root, in, Netlify that tunnel. It's gonna run this command after it clones down the repo in Netlify. We're just basically just building the API project and deploying that as a Netlify function, which ends up being deployed to a device lambda. And then it does also a build for the React application. And just serves that or the static CDN. The Netlify function that gets built is here in source functions GraphQL. It looks very similar to the code for our local GraphQL API, except it uses the Apollo server lambda version of Apollo server. But otherwise, it's still using our makeAugmentedSchema from neo4j GraphQL JS pulling in the GraphQL schema type definitions that we defined. Cool. So that's what Netlify is doing. You can track its progress here. might take a little bit to build the React app. Cool. Anyone have any questions? Don't see anything in the chat. So that's cool. But again, feel free to ask away in the chat. So while this is running, let's get back to talking about our map. So we talked about the requirements that we had for our map in the application, we need to be able to sort of add annotations to it. We need to be able to draw on the map. So sort of the ability to add arbitrary layers, I think most most JavaScript map libraries let us do that. I've used Leaflet in the past, which is an open source JavaScript mapping library, which is pretty nice allows us to add add annotations and things like that. I've also used matte box, Mapbox GL JS, which I believe is based on Leaflet somehow, there's some relation there. I think the maintainer of Leaflet now works at Mapbox, something like that. It has as similar. A similar API, but I think it is maybe a bit more powerful and has integration with Mapbox for things like some custom style and different tile sets, things like that. Not sure what all additional functionality it adds. But I've used both of those. I have also, sort of used some of the React components that wrap these, looks like our Netlify deploy is done. Preview deploy. So let's see what Netlify is it gives us an API or sorry, a URL for each one of our deployments, I just refreshed there, it's getting error initially, I think it just needed to refresh. Cool. So here's the URL for our app, running on Netlify. Talking to our neo4j Aura instance that we just deployed. So we're serving the static React contents to the Netlify CDN, our GraphQL API got deployed to AWS lambda as a Netlify function. And that GraphQL API is querying our neo4j Aura instance, anytime you run a query. Cool. Okay, so we're an hour and a half in. And we're starting to talk about maps. I think let's save the map bit for next week. Seems like a good stopping point. So next week we'll start to explore adding a map component to our application. So maybe instead of here where we're searching. Previously, we could search for users by name or something, it will start to add our property search component there where we have a map view, taking advantage of some of the GraphQL filtering functionality that we built. Cool, so I think we'll call it good there for today. I was gonna say I will push up the code to GitHub. That we worked on today, but we already did that. So that's come up here. So just to recap what we did for today. First, we finished off working with GraphQL architect in neo4j desktop. We were using the GraphQL schema building functionality and GraphQL architects. We then exported that into the project where we were building our GRANDstack app, previously that we had pulled down from the GRANDstack starter project. So we updated the GraphQL API. Then we got our React components that were there previously, for fetching data about business reviews. We updated those. Now to use our property information, to show kind of a simple chart and a simple table, and then we took a look at neo4j Aura. And we provisioned an Aura cluster. And we used the neo4j cloud desktop app, graph app to push a database from neo4j desktop up to Aura that was useful. We had different iterations that we did on data import. So it was useful to be able to do that locally instead of having to do that on Aura each time. Then once we had the database, we were ready to deploy to the Aura cluster. We did that with our neo4j cloud app. And then we deployed our React app and our GraphQL API to Netlify where it is now talking to our Aura instance. Cool. So that's what we did today. Next time, we'll pick up where we left off. Starting with adding a map component, which I was hoped we were gonna get to today, but just ran out of time. So hope you will tune in, next week. As always, it's every Thursday at 2 p.m. Pacific time on the neo4j Twitch channel. So we'll see you next time. Thanks for coming today. Cheers.
Subscribe To Will's Newsletter
Want to know when the next blog post or video is published? Subscribe now!