Search code examples
go

Entgo User "likes" user with through table


I'm using Entgo for a social dating app and I'm having a little problem with generating the schema for "likes". I want to use a through-table so I can store some extra metadata like a created_at timestamp but I can't quite get the edges set up correctly. I need edges to sent_like and received likes - both of type User.

I'm using https://entgo.io/docs/schema-edges/#edge-schema as a reference - and what I'm trying to achieve is something between the friendships example and the user likes tweets example. Attached are my schemas for User and Like. If someone could help me set up the edges for User, I would be hugely grateful!

User Schema

package schema

import (
    "time"

    "entgo.io/ent"
    "entgo.io/ent/schema/edge"
    "entgo.io/ent/schema/field"
    "github.com/go-openapi/strfmt"
    "github.com/google/uuid"
)

// User holds the schema definition for the User entity.
type User struct {
    ent.Schema
}

// Fields of the User.
func (User) Fields() []ent.Field {
    return []ent.Field{
        // Database Timestamps and Versioning
        field.UUID("id", uuid.UUID{}).
            Default(uuid.New).
            StorageKey("oid"),
        field.Time("created_at").
            Default(time.Now).
            Immutable(),
        field.Time("updated_at").
            Default(time.Now).
            UpdateDefault(time.Now),
        field.Time("deleted_at").
            Optional().
            Nillable(),
        field.Int32("version").
            Default(1),
        // User Fields
        field.String("first_name").
            NotEmpty(),
        field.String("last_name").
            NotEmpty(),
    }
}

// Edges of the User.
func (User) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("profile", Profile.Type).
            Unique(),
        edge.To("matches", User.Type),
        // Here is where I'm having trouble!
    }
}

Like Schema

package schema

import (
    "time"

    "entgo.io/ent"
    "entgo.io/ent/schema"
    "entgo.io/ent/schema/edge"
    "entgo.io/ent/schema/field"
    "github.com/google/uuid"
)

// Like holds the schema definition for the Like entity.
type Like struct {
    ent.Schema
}

// Annotations of the Like.
func (Like) Annotations() []schema.Annotation {
    return []schema.Annotation{
        field.ID("sender_id", "receiver_id"),
    }
}

// Fields of the Like.
func (Like) Fields() []ent.Field {
    return []ent.Field{
        field.Time("created_at").
            Default(time.Now).
            Immutable(),
        field.UUID("sender_id", uuid.UUID{}),
        field.UUID("receiver_id", uuid.UUID{}),
    }
}

// Edges of the Like.
func (Like) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("sender", User.Type).
            Required().
            Unique().
            Field("sender_id"),
        edge.To("receiver", User.Type).
            Required().
            Unique().
            Field("receiver_id"),
    }
}

Solution

  • On User:

    edge.To("sentLikes", Like.Type),
    edge.To("receivedLikes", Like.Type),
    

    On Like:

    edge.From("user", User.Type).
            Ref("sentLikes").Field("sender_id").Required().Unique(),
    edge.From("user", User.Type).
            Ref("receivedLikes").Field("receiver_id").Required().Unique(),