Legend* is an open-source data platform created by Goldman Sachs and contributed to the Fintech Open Source Foundation (FINOS).
In this blog, we will first dive into GraphQL, explore how it streamlines the process of accessing data from multiple sources, paving the way for efficient client-server interactions. We will then discuss building a GraphQL service with Legend through an illuminating example, shedding light on its role in streamlining the SDLC while providing a governed server-side runtime.
GraphQL is a declarative API Query language for precise data retrieval. Unlike conventional REST APIs, which often provide fixed data structures, GraphQL empowers clients to dictate the data required in a single query. This core pillar of GraphQL removes the burden on developers to repetitively build APIs for every feature and allows them to focus on core functionality.
Source: https://graphql.org/
Legend provides a GraphQL interface for querying modelled data which works out-of-the-box with no additional configuration. It leverages data models and server-side runtime provided by Legend with compatibility to numerous supported relational databases. These connectors can be used through mapping and runtimes which seamlessly implement GraphQL resolvers, allowing federated data fetching across multiple sources. As we will see below, Legend also provides dynamic filters generated by introspecting the model definitions and extending them to allow clients to search capabilities across the graph with tremendous flexibility.
Building a GraphQL service requires defining a schema of types and various fields on those types. We will leverage data modelling features in Legend to build a schema for our service. One of our previous blog posts Building Platforms for Data Engineering discusses data modelling in Legend and introduces a “Firm-Person” logical model. We will use a similar model for our service with entities Firm and Person, and a one-to-many relationship defined between them as shown in the below diagram.
A GraphQL schema must also define a query type at the root level, which represents all the possible entry points to the service. In Legend, we can define this root query type using another class. And for its top-level fields we will define several derived properties.
Next in building our GraphQL service we will need resolvers for our types and their fields. We will leverage Pure language expressions and mappings discussed in detail in a previous blog post to achieve this. For our top-level fields, we define resolvers using Pure language expressions in the derived properties of query class and for all other object/class types, we will define a mapping. This mapping provides resolvers for fields in respective object/class types. In this example our mapping (and runtime) connects our data model to a relational data source.
Let us look at a simple query which fetches all firms’ legal names.
Next, let us try a different query, to fetch employees of “Stark Industries”. We can use the top-level field employeesByFirm which accepts a firm name as an argument.
For our final example, let us try to fetch employees of “Stark Industries” again but this time using the top-level field employees and a dynamic filter on the firm’s legal name. Dynamic filters do not require to be modelled but rather can be defined directly in GraphQL query.
Apart from querying, Legend also supports introspection of the type-system over its GraphQL API, in adherence to the official specification. This gives users much needed flexibility to use any GraphQL client of their choice. For example, in this blog post, example query snapshots are from an instance of GraphiQL.
Legend also supports GraphQL schema generation from Pure models and vice versa which can be leveraged to integrate Legend into an existing GraphQL ecosystem.
Documentation and Open-Source Code
More presentations, talks and videos can be found on the Legend website
(*) The open-source contributions mentioned in this article relate to data models. The resulting collaborations involve the exchange of non-proprietary, non-confidential, and non-licensed information only.
See https://www.gs.com/disclaimer/global_email for important risk disclosures, conflicts of interest, and other terms and conditions relating to this blog and your reliance on information contained in it.