How to write better graphql schemas?

I want to create two type User and Cluster. I’m writing it in this way:

name: string @index(exact) .
username: string @index(exact) .
bio: string .
age: int .
location: geo .
dob: datetime .
tags: [string] .
connections: [uid] @reverse .
cluster: uid .
radius: int .
participants: int .
maxParticipants: int .
softConnectRadius: int .
connectRadius: int .
premium: bool .
entryCost: int .

type User {
    name: string
    username: string
    bio: string
    age: int
	location: geo
    dob: datetime
    tags: [string]
	connections: [User]
    cluster: Cluster
}

type Cluster {
	name: string
	bio: string
	location: geo
	radius: int
	participants: int
	maxParticipants: int
	softConnectRadius: int
	connectRadius: int
	premium: bool
	entryCost: int
}

I’m wondering if in case I want to add more types, then this will create confusion for fields. Is there any other way to write schemas? I tried other methods but they failed to load in dgraph.

This is not a GraphQL Schema neither DQL Schema. It looks like you’re mixing the two. This scheme will not work in DQL or GraphQL. Perhaps you are just theorizing and not in practice.

If you create a Schema via GraphQL. Avoid making modifications on the DQL side so as not to break the GraphQL layer.

You can add Types at any time. And modify them naturally.

I tried writing it like this:

type User {
	name: string @index(exact) .
	username: string @index(exact) .
	bio: string
	age: int
	location: geo
	dob: datetime
	tags: [string]
	connections: [User]
	cluster: Cluster
}

Got this error: Expected new line after field declaration. Got @.

Can you point me to the right docs where I can see how to write schemas?

Assuming you are doing GraphQL this is the one Administrative API - GraphQL

For how to write GraphQL schema, start at this page and see the child doc pages

https://dgraph.io/docs/graphql/schema/

I wrote this schema

User.name: string @index(exact) .
User.username: string @index(exact) .
User.bio: string .
User.age: int .
User.loc: geo @index(geo) .
User.dob: datetime .
User.tags: [string] .
User.connections: [uid] .
User.cluster: uid .

type User {
    User.name
    User.username
    User.bio
    User.age
	User.loc
	User.dob
    User.tags
	User.connections
    User.cluster
}

Cluster.name: string @index(exact) .
Cluster.bio: string .
Cluster.loc: geo @index(geo) .
Cluster.radius: int .
Cluster.participants: int .
Cluster.maxParticipants: int .
Cluster.softConnectRadius: int .
Cluster.connectRadius: int .
Cluster.premium: bool .
Cluster.entryCost: int .
Cluster.blockedUsers: [uid] .

type Cluster {
	Cluster.name
	Cluster.bio
	Cluster.loc
	Cluster.radius
	Cluster.participants
	Cluster.maxParticipants
	Cluster.softConnectRadius
	Cluster.connectRadius
	Cluster.premium
	Cluster.entryCost
	Cluster.blockedUsers
}

Running this query on this schema say Predicate loc is not indexed

`query users($a: string) {
		users(func: type(User)) @filter(near(loc, [1, 2], 100000000)) {
			uid
            name
            username
            bio
            loc
            dob
            tags
			cluster {
				name
				bio
				radius
				loc
			}
		}
	}`

Change to
@filter(near(User.loc, [1, 2], 100000000))

The query with filter

@filter(eq(name, $a))

Works without User.name but loc doesn’t? Also it gives empty array everytime as response when I use User.loc.

Hey Johri,

You see, the probability of a user making an error is higher than that of a computer, right? You started this thread talking about building a GraphQL Schema. You didn’t quite explain what you’re doing, but based on what you’ve written, it seems you might be mixing things up. You seem to be confusing DQL Schema with GraphQL. These are two distinct things. However, from your last post, it seems you’re improving in DQL and modeling following the GraphQL standard. I’m a bit confused as to why you’re writing DQL Schemas if you’re working with GraphQL. But let’s unpack this.

The “@filter(eq(name, $a))” part shouldn’t work if your model is the last one you presented. If it did work, you might have done something wrong. Perhaps you didn’t delete previous data or didn’t start the database from scratch.

Let’s agree on the following. Start from absolute zero. Delete everything (of course, if it’s not sensitive data). And stick to one model. Don’t use “name”, always use “User.name” and don’t change that. Update any mutations if you still have any in that format. It’s actually good if you use this model because it will make your data compatible with GraphQL, if you gonna use it in the future, and improve the overall performance of the Cluster.

But understand, if it worked without “User.”, it means you’re doing something wrong. And it’s likely because you forgot to clean the database.

Once you’ve given this a try, I’d be curious to hear how it worked out for you. So, let me know! And of course, feel free to ask if you have any more questions. I’m here to help!

Cheers.

Hey Michel,

I created this schema for user,

User.key: string @index(exact) .
User.name: string @index(exact) .
User.username: string @index(exact) .
User.bio: string .
User.age: int .
User.location: geo @index(geo) .
User.dob: datetime .
User.tags: [string] .
User.cluster: uid @reverse .

type User {
    User.key
    User.name
    User.username
    User.bio
    User.age
	User.location
	User.dob
    User.tags
    User.cluster
}

I’m using dgraph with go, so I created a struct

type User struct {
	Uid      string      `json:"uid,omitempty"`
	DType    string      `json:"dgraph.type,omitempty"`
	Key      string      `json:"User.key,omitempty"`
	Name     string      `json:"User.name,omitempty"`
	Username string      `json:"User.username,omitempty"`
	Bio      string      `json:"User.bio,omitempty"`
	Age      int         `json:"User.age,omitempty"`
	Location Loc         `json:"User.location,omitempty"`
	Dob      time.Time   `json:"User.dob,omitempty"`
	Tags     []string    `json:"User.tags,omitempty"`
	Cluster  ClusterEdge `json:"User.cluster,omitempty"`
}

I don’t know whether this is the best way to write this schema or am I doing something wrong here, because I will have to create a new struct in go to handle data coming in the rest api request, or to send data back to client. Client can’t get keys like User.name in the api response, it will need name as key. Is there a better way to handle this in dgraph? I saw I can give alias to query like this:

query all($key: string) {
	user(func: eq(User.key, $key)) {
		uid
		key: User.key
		name: User.name
	}
 }

But still have to create a struct to set data in dgraph.

This is a Go demand. In go you have to be strict. If you wanna avoid go’s rules, use JS or Python.