Do custom Graphql DQL queries work with `@recurse` directive?

I am trying to get implement a custom DQL query along with @recurse directive, but it is not working as I would expect it.

This is the code for the custom query

type Query {
    queryChildrenByNode(title: String!): [Node] @custom(dql: """
        query q($title: string) {
            queryChildrenByNode(func: eq(title, $title)) {
                nodeId: uid
                title: Node.title
                value: Node.value
                children: Node.children
        }}""")
}

running the DQL query directly like this works and gives me the desired results

 query {
  queryChildrenByNode(func: eq(Node.title, "today")) @recurse  {
    nodeId: uid
    title: Node.title
    value: Node.value
    children: Node.children
	}
}

but running the Graphql query like this does not

{
  queryChildrenByNode(title: "today") {
    nodeId
    title
    value
  }
}

I am wondering if there is any way to get this working? I want to basically get the subtree of my graph starting from a certain node, but in Graphql.

here is my schema

type Node @withSubscription {
    title: String @search(by: [exact])
    value: String @search(by: [fulltext])
    children: [Node] @hasInverse(field: parent)
    parent: Node
    nodeId: ID!
}

type Query {
    queryChildrenByNode(title: String!): [Node] @custom(dql: """
        query q($title: string) {
            queryChildrenByNode(func: eq(title, $title)) {
                nodeId: uid
                title: Node.title
                value: Node.value
                children: Node.children
        }}""")
}

Hi @amin,

Welcome to Dgraph Community !!

Custom DQL does work with @recurse . I believe the reason the query didn’t work is because you have func: eq(title, $title) instead of func: eq(Node.title, $title) inside the custom DQL query.

If you want to get subgraph starting from a node, you could also use the generated queryNode query providing it with the right filter.

Hi @rajas,

Thank you for the quick answer. I have tried the change you suggested, but I still did not get the results I was expecting.

here is the response I get on DQL

"data": {
    "queryChildrenByNode": [
      {
        "nodeId": "0x4e21",
        "title": "today"
      },
      {
        "nodeId": "0x4e22",
        "title": "today",
        "children": [
          {
            "nodeId": "0x4e23",
            "value": "this is a child",
            "children": [
              {
                "nodeId": "0x4e24",
                "value": "this is a grand child"
              },
              {
                "nodeId": "0x4e25",
                "value": "this is a second grand child"
              }
            ]
          },
          {
            "nodeId": "0x4e26",
            "value": "this is a second child"
          }
        ]
      }
    ]
  },

and here is the result of running the following graphql query

query MyQuery {
  queryChildrenByNode(title: "today") {
    nodeId
    value
    title
    children {
      nodeId
    }
  }
}
 "data": {
    "queryChildrenByNode": [
      {
        "nodeId": "0x4e21",
        "value": null,
        "title": "today",
        "children": []
      },
      {
        "nodeId": "0x4e22",
        "value": null,
        "title": "today",
        "children": []
      }
    ]
  },

As you can see it is not the same data. I would like to get the data, so if you can guide me how to do it using queryNode or fix the current DQL custom query that would be greatly appreciated :pray:t2:

What version of Dgraph are you using. I tried reproducing this with master version. But, the query seemed to work fine.

If you want to get subtree of a graph, starting with a node, you could also use the GraphQL query directly. A custom DQL query for this purpose is an overkill.

query{
  queryNode(filter:{title:{eq:"today"}}){
    title
    children{
      title
      children{
        title
      }
    }
  }
}

I am not sure if it is overkill, the query you have provided seems to only return three levels deep, but what I want is to return the subtree no matter what depth there is, I don’t think I can do that with just Graphql :thinking:

Also, I am using Slash Graphql, so whatever version is deployed and used there (I assume latest)

You may go as much deep as you want in GraphQL.

Even if you use customDQL, the number of levels deep the query results are, depends on what you have queried.

query MyQuery {
  queryChildrenByNode(title: "today") {
    nodeId
    title
    children {
      nodeId
    }
  }
}

will show results upto one level.

query MyQuery {
  queryChildrenByNode(title: "today") {
    nodeId
    title
    children {
      nodeId
      title
      children {
        nodeId
        title
      }
    }
  }
}

will show values for 2 levels and so on.

Just because @recurse custom DQL query is used, it does not mean that data at all levels would be shown.

1 Like

huh. that is a bummer :disappointed: Now I understand why you think it is an overkill :sweat_smile:
So as it stands there is no way to get an unknown level deep tree with just Graphql :disappointed: I would have to run a query using DQL.
Do you know if Slash Graphql exposes a way to run DQL queries directly? (not using Graphql)

It is possible. You could use the /query endpoint. You may read more details here . Depending on your use case, you could use http, grpc or any other Dgraph client.

1 Like

That would actually break the GraphQL specification … unless we had some way to type out an object such as JSON

Sorry for resurrecting an old thread, but couldn’t you perform your query, let’s say it goes 5 levels deep. Let’s also call the nodes that exist at the 5th level ‘leaf’ nodes. If you return the IDs of the nodes, and also a boolean that tells you whether a given node has child nodes or not, for any leaf nodes that do have children, you submit another query. Of course, depending on the data this could generate a lot of queries and you might end up needing logic to mitigate that problem.

I can imagine using datascript - npm (an in-memory clientside database used by https://roamresearch.com and others) to cache complex nested data, because it probably goes beyond the scope of a simple query cache like Apollo’s for example. EDIT: Then you avoid having to re-run these queries, you gradually build up the client-side data (and it’s even queriable with datascript).

Curious how you solved this problem in the end?