How to Build a Flight Network Analysis Graph-Based ASP.NET Application with Memgraph, C#, and D3.js
Introduction
Relational databases are still the norm when it comes to storing data and are often the de facto choice for developers when building any type of application. Although relational databases are versatile, there are certain use cases that are more fitted for different types of database systems such as - graph databases. For example, when your dataset is deeply interconnected, storing it in a SQL database can result in a lot of complex queries and JOIN operations. For this type of use-case, using a graph database can make your life much easier.
In this tutorial, you will learn how to build a flight network analysis graph-based ASP.NET application using Memgraph, C#, and D3.js.
Prerequisites
Before you start building your application, you will need the following:
- An installation of Memgraph DB: a native, in-memory database. To install Memgraph DB and set it up, please follow the instructions on the Installation guide.
- (Optional) An installation of Docker: an open platform for developing, shipping, and running applications.
- (Optional) Memgraph Lab: a desktop application for querying and visualizing your Memgraph data.
Importing the Dataset
Before you start working on your ASP.NET application, you need to import your dataset into Memgraph. For this tutorial, you will be using a flight network dataset containing a subset of flights from 2015.
The dataset consists of US airports. Each airport has an IATA (location identifier), name, city and state, and a geographical location - latitude and longitude. Airports are connected via flights, which contain the flight number, the operating airline name, the flight date, the time of departure, and the flight distance.
To import the data, please follow the Import tool guide.
If you use the CSV import tool, use this dataset.
If you decide to use Cypher queries with mgconsole
, use these Cypher queries.
If you decide to import Cypher queries using Memgraph Lab, make sure to use these Cypher queries.
Creating the Project Structure
For this tutorial, you will be using Visual Studio 2019 on Windows 10 to develop the application. The steps might be slightly different for other IDEs.
- Open Visual Studio and create an empty ASP.NET Core Web Application project.
- Name your project MemFlights (or any name you want), choose an appropriate location, and click Create.
- In Visual Studio, select Tools > NuGet Package Manager > Manage NuGet Packages for Solutions
- Type Neo4j.Driver.Simple in the search box, select it, and click Install.
Now, you should be ready to create a simple application. The first step is to establish a connection with the database. To do this, find Startup.cs in Solution Explorer and open it. Locate the ConfigureServices
method and add the following code:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IFlightsRepository, FlightsRepository>();
services.AddSingleton(GraphDatabase.Driver(
"bolt://localhost:7687",
AuthTokens.None
));
}
This part of the code will allow your application to connect to the database.
Communicating with Database
Now that you’ve established the connection with your database, you are ready to fetch your data and display it! Create a new folder called Repository and make a new class called FlightRepository.cs. You will create a method FetchGraph
which will get your data and place it in a format compatible with D3.js - a JSON-like structure that consists of two lists: nodes and links which are the essential building blocks of the graph.
public async Task<D3Graph> FetchD3Graph(int limit)
{
var session = _driver.AsyncSession(WithDatabase);
try
{
return await session.ReadTransactionAsync(async transaction =>
{
var cursor = await transaction.RunAsync(@"MATCH (origin:Airport)-[f:IS_FLYING_TO]->(dest:Airport) " +
"WITH origin, dest ORDER BY origin.name, dest.name " +
"RETURN origin.NAME AS origin_air, dest.NAME AS dest_air", new { limit });
var nodes = new List<D3Node>();
var links = new List<D3Link>();
var records = await cursor.ToListAsync();
foreach (var record in records)
{
var orgAirport = new D3Node(title: record["origin_air"].As<string>(), label: "airport");
var originAirportIndex = nodes.Count;
nodes.Add(orgAirport);
var destAirport = new D3Node(record["dest_air"].As<string>(), "airport");
var destAirportIndex = nodes.IndexOf(destAirport);
destAirportIndex = destAirportIndex == -1 ? nodes.Count : destAirportIndex;
nodes.Add(destAirport);
links.Add(new D3Link(destAirport.Title, orgAirport.Title));
}
return new D3Graph(nodes, links);
});
}
finally {
await session.CloseAsync();
}
}
You are now ready to execute your first graph query:
MATCH (origin:Airport)-[f:IS_FLYING_TO]->(dest:Airport)
WITH origin, dest
ORDER BY origin.name, dest.name
RETURN origin.NAME AS origin_air, dest.NAME AS dest_air;
This query will return all of the origin and destination airports that have flights between them. All of the objects are stored in key-value pairs which will later be converted into JSON format. The end result will be a JSON object containing:
nodes
- all of the nodes(airports) from the graph.links
- all of the relationships between source and target nodes.
Visualizing the Graph Data
Now that you have some results, it's time to visualize them. To do so, you will use D3.js, a JavaScript library for manipulating document-based data. If you want to learn more about D3.js, you should visit their official website.
Create a wwwroot
folder and add index.html
file. This file will contain your function to visualize the graph.
To include D3.js into your webpage, simply add <script src="https://d3js.org/d3.v6.min.js" charset="utf-8"></script>
to the header of the file.
Next, you need to collect the data from your application. You can do this with the following function:
d3.json("/graph").then(function (graph) {
const links = graph.links.map(d => Object.create(d));
const nodes = graph.nodes.map(d => Object.create(d));
Now that the data is collected, you need to create the nodes and relationships that will be showcased in your graph. To accomplish this, you can use the following code:
const link = g.append("g").selectAll("lines")
.data(links).enter().append("line").attr("class", "link");
const node = g.append("g").selectAll("circle")
.data(nodes).enter().append("circle")
.attr("class", function (d) { return "node " + d.label; })
.attr("r", 10)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
You can find the full code here!
You should now have a graph visualization similar to the one below and be able to drag nodes around.
You can find the entire code for this tutorial in this GitHub repository.
Conclusion
Even though graph databases have been around for a long time, they are considered a new technology. They offer a lot of different possibilities and are a powerful tool for any use-case that involves highly interconnected data and complex traversals.
In this tutorial, you learned how to build a simple .NET graph application using Memgraph, C#, and D3.js. You learned how to import your data into Memgraph, communicate with the database using the C# client, run Cypher queries, and visualize the results with D3.js.
Now that you are familiar with Memgraph, you should definitely try some of our other tutorials, or even better, build your own application.
If at any point you need help, feel free to post your questions on StackOverflow with the tag memgraphdb
or on our Discord server.