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 predicatesmutation or theexpand allquery, Dgraph will check if the node has adgraph.typepredicate. 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.typepredicate), then you can use the functiontype()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.<>