How to query for arbitrary predicate and get the uids along with the predicate

Now the issue is I want to make the predicate arbitrary while writing this query

You can make it arbitrary to a limited extent. And that extent is that it must be defined in your schema types.

Let’s say you have this schema:

sections: [uid] .
paragraphs: [uid] .
name: string .
title: string .
text: string .

type Document {
  name
  sections
}

type Section {
  sections
  paragraphs
}

type Note {
  text
}

type Paragraph {
  text
}

With some data:

  _:doc1 <dgraph.type> "Document" .
  _:doc1 <name> "My First Document" .
  _:doc1 <sections> _:section1 .
  _:section1 <dgraph.type> "Section" .
  _:section1 <title> "foo" .
  _:section1 <sections> _:section2 .
  _:section2 <dgraph.type> "Section" .
  _:section2 <title> "bar" .
  _:section1 <sections> _:section3 .
  _:section3 <dgraph.type> "Section" .
  _:section3 <title> "baz" .
  _:doc1 <notes> _:note1 .
  _:note1 <dgraph.type> "Note" .
  _:note1 <text> "Lorem Ipsum" .

Now you can arbitrary query for sections and paragraphs of the document, but not the notes, because the note predicate is not part of the type schema for the Document not the Section

query {
  docs(func: type(Document)) {
    uid
    expand(_all_) {
      uid
      expand(_all_) {
        uid
      }
    }
  }
}

If you want the notes that may exist but are not included within the types, then you would have to add them imperatively:

query {
  docs(func: type(Document)) {
    uid
    notes {
      uid
      text
    }
    expand(_all_) {
      uid
      expand(_all_) {
        uid
      }
    }
  }
}

This may be confusing because in an older version of Dgraph, the expand(_all_) use to include every predicate that existed for the nodes selected. But in recent versions the algorithm was changed to only included the typed predicates.

And FWIW, this is also the case for deletes as well. Older Dgraph versions use to delete all predicates that were attached to a node with the S** delete methods, but now, only predicates specifically typed to the node are deleted.

And if for whatever reason your nodes don’t have a dgraph.type predicate, then you can not use the expand(_all_) nor the S** syntax effectively. This almost forces you to use Dgraph in a typed manner instead of the older envision of a schema-less database. The predicates do get generated if you just provide the data, but the types and predicates those types include are not generated for you.

https://dgraph.io/docs/dql/dql-schema/#when-to-use-node-types

Node types are optional, but there are two use cases where actually knowing the list of potential predicates of a node is necessary:

  • deleting all the information about a node: this is the delete { <uid> * * . } mutation.
  • retrieving all the predicates of a given node: this is done using the expand(_all_) feature of DQL.

The Dgraph node types are used in those 2 use cases: when executing the delete all predicates mutation or the expand all query, Dgraph will check if the node has a dgraph.type predicate. If so, the engine is using the declared type to find the list of predicates and apply the delete or the expand on all of them.

When nodes have a type (i.e have a dgraph.type predicate), then you can use the function type() in queries.

Warning delete { <uid> * * . } will only delete the predicates declared in the type. You may have added other predicates by running DQL mutation on this node: the node may still exist after the operation if it holds predicates not declared in the node type. <>

1 Like