Graphql query translated to DQL - filtering

I’m attempting to translate a working Graphql query into a DQL equivalent, and could use a nudge in the right direction. I think this is pretty basic, but the docs aren’t quite getting me there.

The Types are as basic as they come.

type Item {
	id: ID! 
	title: String!
	description: String
	user: User!
}  

type User {
	id: ID! 
	displayName: String 
	email: String!
    items: [Item] @hasInverse(field: creator)
}

And the graphql query is just pulling items filtered on the user ID.

query AllItems($id: ID!) {
	queryItem {
		id
		title
		description
		user(filter: {id: [$id]}) {
			id
		}
	}
}

Now I want to do the same thing with a custom DQL query.

queryUserItems(id: ID!): [Item] @custom(dql: """  
	query {
		queryUserItems(func: type(Item)) {
			id: uid
			title: Item.title
			description: Item.description
    			user: Item.user {
    				id: uid 
    				email: User.email
  			}
		}
	}
""")

With the $id Input variable I’ve been trying to use variations of @filter(uid_in(User.id, uid($id))) but this produces a Failed with status code 401 error. Am I approaching this all wrong? I’d be very appreciative of any tips for how to achieve a output equivalent to the initial graphql statement.

Note: I’m currently on Dgraph Cloud shared.

UPDATE: I’ve made some progress–no more error!– but the results are still not being filtered. Here’s my current query:

queryUserItems(id: String!): [Item] @custom(dql: """  
    query q($id: string) {
      queryUserItems(func: type(Item)) {
        id: uid
        description: Item.description
        title: Item.title
    	user: Item.user @filter(uid_in(id,0x82f21700)) {
    		id: uid
    		email: User.email
  	}
      }
}
""")

And the corresponding request:

query MyQuery {
  queryUserItems(id: "0x82f21700") {
    myTitle
    id
  }
}

You can see the example hard codes the uid, though I’ve tried passing it in as the variable as well. The list of Items returned is the full list, not fitered by user id. The documentation says the result should only contain the filtered items, but it is returning them all. A potential clue: once the filter is applied I cannot return user edge results–it returns the error : "Non-nullable field 'user' (type User!) was not present in result from Dgraph. To me that implies the user edge is being filtered out, but it’s not propagating up to the parent node.

Okay, got it working. As some of the documentation points out, there is a non-trivial mental shift going from a relational db mindset (or even vanilla Graphql mindset) to a native graph db mindset. I can see how this will become intuitive with some practice. Anyway, here’s the answer (or at least the one I arrived at by reviewing the documentation examples more carefully, and experimenting with Ratel). I hope it’s useful for other new users getting the hang of this.

type Query {
	queryMyItems(id: String!): [Item] @custom(dql: """  
		query q($id: string) {
  			var(func:uid($id)){
    			MyItems as User.items
  			}    
  		queryMyItems(func:uid(MyItems)){
			title: Item.title
    		id: uid
  		}
	}
  """)
}

The trick is to use query variables [https://dgraph.io/docs/query-language/query-variables/] to first generate the items linked to a given user, and then to return them as the Item type via graphql. Simple idea, really.

1 Like