We’re going to create a simple social network where users can follow each other and create posts.

Full code

Schema:

 N::User {
    name: String,
    age: U32,
    email: String,
    created_at: Date DEFAULT NOW,
    updated_at: Date DEFAULT NOW,
}

N::Post {
    content: String,
    created_at: Date DEFAULT NOW,
    updated_at: Date DEFAULT NOW,
}

E::Follows {
    From: User,
    To: User,
    Properties: {
        since: Date DEFAULT NOW,
    }
}

E::Created {
    From: User,
    To: Post,
    Properties: {
        created_at: Date DEFAULT NOW,
    }
}

Queries:

QUERY CreateUser(name: String, age: U32, email: String) =>
    user <- AddN<User>({name: name, age: age, email: email})
    RETURN user


QUERY CreateFollow(follower_id: ID, followed_id: ID) =>
    follower <- N<User>(follower_id)
    followed <- N<User>(followed_id)
    AddE<Follows>::From(follower)::To(followed) // don't need to specify the `since` property because it has a default value
    RETURN "success"


QUERY CreatePost(user_id: ID, content: String) =>
    user <- N<User>(user_id)
    post <- AddN<Post>({content: content})
    AddE<Created>::From(user)::To(post) // don't need to specify the `created_at` property because it has a default value
    RETURN post


QUERY GetUsers() =>
    users <- N<User>
    RETURN users

QUERY GetPosts() =>
    posts <- N<Post>
    RETURN posts

QUERY GetPostsByUser(user_id: ID) =>
    posts <- N<User>(user_id)::Out<Created>
    RETURN posts


QUERY GetFollowedUsers(user_id: ID) =>
    followed <- N<User>(user_id)::Out<Follows>
    RETURN followed

QUERY GetFollowedUsersPosts(user_id: ID) =>
    followers <- N<User>(user_id)::Out<Follows>
    posts <- followers::Out<Created>::RANGE(0, 40)
    RETURN posts::{
        post: _::{content},
        creatorID: _::In<Created>::ID,
    }

Prerequisites

Install the HelixDB CLI:

curl -sSL https://helix.sh/install.sh | bash

Install the Helix container:

helix install

Initialise a new project:

helix init

Step 1: Define the schema in schema.hx

We’re going to define the schema for our social network in schema.hx. We’re going to have User nodes where users can Follow other users. We’re also going to have Post nodes where users can Create posts.

N::User {
    name: String,
    age: U32,
    email: String,
    created_at: Date DEFAULT NOW,
    updated_at: Date DEFAULT NOW,
}

N::Post {
    content: String,
    created_at: Date DEFAULT NOW,
    updated_at: Date DEFAULT NOW,
}

E::Follows {
    From: User,
    To: User,
    Properties: {
        since: Date DEFAULT NOW,
    }
}

E::Created {
    From: User,
    To: Post,
    Properties: {
        created_at: Date DEFAULT NOW,
    }
}

Step 2: Inserting data

Creating a user is done by inserting a new node into the graph.

QUERY CreateUser(name: String, age: U32, email: String) =>
    user <- AddN<User>({name: name, age: age, email: email})
    RETURN user

To let users follow another user, we need to create an edge between them.

QUERY CreateFollow(follower_id: ID, followed_id: ID) =>
    follower <- N<User>(follower_id)
    followed <- N<User>(followed_id)
    AddE<Follows>::From(follower)::To(followed) // don't need to specify the `since` property because it has a default value
    RETURN "success"

To create a post, we need to create a post node and an edge between the user and the post.

QUERY CreatePost(user_id: ID, content: String) =>
    user <- N<User>(user_id)
    post <- AddN<Post>({content: content})
    AddE<Created>::From(user)::To(post) // don't need to specify the `created_at` property because it has a default value
    RETURN post

Step 3: Query the data

To get all users, we can use the following query:

QUERY GetUsers() =>
    users <- N<User>
    RETURN users

To get all posts, we can use the following query:

QUERY GetPosts() =>
    posts <- N<Post>
    RETURN posts

To get all posts by a user, we can use the following query:

QUERY GetPostsByUser(user_id: ID) =>
    posts <- N<User>(user_id)::Out<Created>
    RETURN posts

To get all users that a user follows, we can use the following query:

QUERY GetFollowedUsers(user_id: ID) =>
    followed <- N<User>(user_id)::Out<Follows>
    RETURN followed

As a more complex example, we could have a query that loads an page containing the posts of users that a user follows. To do this we are going to remap the posts to have a field containing information about the user that created the post.

QUERY GetFollowedUsersPosts(user_id: ID) =>
    followers <- N<User>(user_id)::Out<Follows>
    posts <- followers::Out<Created>::RANGE(0, 40)
    RETURN posts::{
        post: _::{content},
        creatorID: _::In<Created>::ID,
    }

Step 4: Run the queries

To run the queries, we can use the following command:

helix deploy