Modus makes it simple to fetch data from external sources. The specific data
source you’re retrieving from determines the method you use to interact with it.
Fetching from databases
PostgreSQL
PostgreSQL is a powerful, open source relational database system. Modus provides
a simple way to interact with PostgreSQL databases with the postgresql
APIs.
Here is an example of fetching a person from a PostgreSQL database using the
Modus SDK:
package main
import (
"github.com/hypermodeinc/modus/sdk/go/pkg/postgresql"
)
// the name of the PostgreSQL connection, as specified in the modus.json manifest
const connection = "my-database"
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func GetPerson(name string) (*Person, error) {
const query = "select * from persons where name = $1"
rows, _, _ := postgresql.Query[Person](connection, query, name)
return &rows[0], nil
}
Dgraph
Dgraph is a distributed, transactional graph database. Modus offers an easy way
to query and mutate data in Dgraph with the dgraph
APIs.
Here is an example of fetching a person from a Dgraph database using the Modus
SDK:
package main
import (
"encoding/json"
"github.com/hypermodeinc/modus/sdk/go/pkg/dgraph"
)
// the name of the Dgraph connection, as specified in the modus.json manifest
const connection = "my-dgraph"
// declare structures used to parse the JSON document returned by Dgraph query.
type Person struct {
Name string `json:"name,omitempty"`
Age int32 `json:"age,omitempty"`
}
// Dgraph returns an array of Persons
type GetPersonResponse struct {
Persons []*Person `json:"persons"`
}
func GetPerson(name string) (*Person, error) {
statement := `query getPerson($name: string!) {
persons(func: eq(name, $name)) {
name
age
}
}
`
variables := map[string]string{
"$name": name,
}
response, _ := dgraph.Execute(connection, &dgraph.Request{
Query: &dgraph.Query{
Query: statement,
Variables: variables,
},
})
var data GetPersonResponse
json.Unmarshal([]byte(response.Json), &data)
return data.Persons[0], nil
}
Neo4j
Neo4j is a graph database management system. Modus provides a simple way to
query and mutate data in Neo4j with the neo4j
APIs.
Here is an example of mutating & fetching a person from a Neo4j database using
the Modus SDK:
package main
import (
"github.com/hypermodeinc/modus/sdk/go/pkg/neo4j"
)
const host = "my-database"
func CreatePeopleAndRelationships() (string, error) {
people := []map[string]any{
{"name": "Alice", "age": 42, "friends": []string{"Bob", "Peter", "Anna"}},
{"name": "Bob", "age": 19},
{"name": "Peter", "age": 50},
{"name": "Anna", "age": 30},
}
for _, person := range people {
_, err := neo4j.ExecuteQuery(host,
"MERGE (p:Person {name: $person.name, age: $person.age})",
map[string]any{"person": person})
if err != nil {
return "", err
}
}
for _, person := range people {
if person["friends"] != "" {
_, err := neo4j.ExecuteQuery(host, `
MATCH (p:Person {name: $person.name})
UNWIND $person.friends AS friend_name
MATCH (friend:Person {name: friend_name})
MERGE (p)-[:KNOWS]->(friend)
`, map[string]any{
"person": person,
})
if err != nil {
return "", err
}
}
}
return "People and relationships created successfully", nil
}
type Person struct {
Name string `json:"name"`
Age int64 `json:"age"`
}
func GetAliceFriendsUnder40() ([]Person, error) {
response, err := neo4j.ExecuteQuery(host, `
MATCH (p:Person {name: $name})-[:KNOWS]-(friend:Person)
WHERE friend.age < $age
RETURN friend
`,
map[string]any{
"name": "Alice",
"age": 40,
},
neo4j.WithDbName("neo4j"),
)
if err != nil {
return nil, err
}
nodeRecords := make([]Person, len(response.Records))
for i, record := range response.Records {
node, _ := neo4j.GetRecordValue[neo4j.Node](record, "friend")
name, err := neo4j.GetProperty[string](&node, "name")
if err != nil {
return nil, err
}
age, err := neo4j.GetProperty[int64](&node, "age")
if err != nil {
return nil, err
}
nodeRecords[i] = Person{
Name: name,
Age: age,
}
}
return nodeRecords, nil
}
Fetching from APIs
HTTP
HTTP protocols underpin RESTful APIs with OpenAPI schemas. Modus provides a
convenient way to interact with any external HTTP API using the http
APIs in
the Modus SDK.
Here is an example of fetching a person from an HTTP API using the Modus SDK:
package main
import (
"encoding/json"
"fmt"
"github.com/hypermodeinc/modus/sdk/go/pkg/http"
)
// declare structures used to parse the JSON document returned by the REST API
type Person struct {
Name string `json:"name,omitempty"`
Age int32 `json:"age,omitempty"`
}
func GetPerson(name string) (*Person, error) {
url := fmt.Sprintf("https://example.com/api/person?name=%s", name)
response, _ := http.Fetch(url)
// The API returns Person object as JSON
var person Person
response.JSON(&person)
return person, nil
}
GraphQL
GraphQL is a data-centric query language for APIs that allows you to fetch only
the data you need. With the graphql
APIs in the Modus SDK, you can easily
fetch data from any GraphQL endpoint.
Here is an example of fetching a person from a GraphQL API using the Modus SDK:
import (
"encoding/json"
"github.com/hypermodeinc/modus/sdk/go/pkg/graphql"
)
// the name of the GraphQL connection, as specified in the modus.json manifest
const connection = "my-graphql-api"
// declare structures used to parse the JSON document returned
type Person struct {
Name string `json:"name,omitempty"`
Age int32 `json:"age,omitempty"`
}
type GetPersonResponse struct {
Person *Person `json:"getPerson"`
}
func GetPerson(name string) (*Person, error) {
statement := `query getPerson($name: String!) {
getPerson(name: $name) {
age
name
}
}`
vars := map[string]any{
"name": name,
}
response, _ := graphql.Execute[GetPersonResponse](connection, statement, vars)
return response.Data.Person, nil
}