Query<T, R>
A Query is an immutable object used to build queries on the datacloud. It is a graph query builder.
It starts from an origin
InstanceOrTag (typically, the InstanceOrTag
of a data type or of an instance).
From there, it can follow relations between data types and filter results.
Example:
origin --a--> X --b--> Y --c--> Z
Example:
Query.from(origin)
.follow(a)
.execute();
This will return a Promise of a QueryResult whose values are of type X: Promise<QueryResult<X>>
.
A query defines a starting working set of nodes and operations that will mutate it.
From our example,the working set is first the origin
graph node. Then the follow
operations create a new working set only containing the nodes related to the origin through relation a
.
Multiple relations can be followed at once to create the equivalent of JOIN operations in relational databases.
Query.from(origin)
.follow(a).andReturn()
.follow(b)
.follow(c).andReturn()
.execute();
The next operation defines a working set containing the nodes related
through relation b
to nodes that are related through relation a
to the origin.
A similar operation is defined for relation c
.
At each level, "andReturn()" method can be called to add the current level to the result.
This will return a Promise of a QueryResult whose values are of type [X, Z]: Promise<QueryResult<[X, Z]>>
.
Out of the 4 working sets created, only the second and fourth are flagged to be returned and part of the result.
But the operations in the middle impact this result: e.g.,
all returned tuples (t1, t2) are object that have an intermediate i
of type Y.
such that t1 --b-> i --c-> t2
but the i
was not flagged to be returned.
Queries define a path from a starting point following a specific list of relations. As explained with our example, only nodes part of a full path can be returned.
A query can be executed with 3 different ways:
- execute(): it runs the query on the datacloud and return the result as a QueryResult.
- observe(): it runs the query on the datacloud and subscribes to updates. It returns an Observable which provides a new QueryResult every time the result changes.
- executeFromCache(): it runs the query on the local datacloud which may be incomplete view of the datacloud (it is the local cache). It is executed synchronously.
Type Parameters
Type Parameter |
---|
T extends CloudObject |
R |
Constructors
new Query()
new Query<T, R>(): Query<T, R>
Returns
Query
<T
, R
>
Methods
followRule()
static followRule<T>(
ctx,
root,
rule,
source?,
options?): Observable<QueryResult<T extends CloudObject ? T<T> : CloudObject>>
Create a query starting from a specific root instance, then following relations based on a rule constraint.
Type Parameters
Type Parameter |
---|
T extends InstanceOrTag |
Parameters
Parameter | Type | Description |
---|---|---|
ctx | Context | Context in which the Query is observed |
root | T | Starting point of the query. See root of RootQueryPart |
rule | FollowRule | Discriminate which relations to follow |
source ? | string | The tag of the source responsible for executing the query |
options ? | ImplicitQueryOption | options |
Returns
Observable
<QueryResult
<T
extends CloudObject
? T
<T
> : CloudObject
>>
from()
static from<T>(tag, source?): Query<T extends CloudObject ? T<T> : CloudObject, never>
Create a query starting from the CloudObject
specified tag.
That CloudObject
must already exist in the local database. In case you have the tag as a string
and need to get
the object from a remote database, use Query.fromTag instead.
Type Parameters
Type Parameter |
---|
T extends InstanceOrTag |
Parameters
Parameter | Type | Description |
---|---|---|
tag | T | tag of the CloudObject the query is starting from |
source ? | string | optional source of the data to answer the query |
Returns
Query
<T
extends CloudObject
? T
<T
> : CloudObject
, never
>
an empty Query whose starting point is defined by a single CloudObject
fromTag()
static fromTag<T>(
tag,
dataType,
source?): Query<T, never>
Create a query starting from the CloudObject
specified tag.
The difference with Query.from method is that you specify the data type of the Tag: this allows to execute
queries with a tag that is unknown by the local database, on the right remote database.
Type Parameters
Type Parameter |
---|
T extends CloudObject |
Parameters
Parameter | Type | Description |
---|---|---|
tag | string | tag of the CloudObject the query is starting from |
dataType | InstanceOrTag | Class <T > | data type of the tag CloudObject . |
source ? | string | optional source of the data to answer the query |
Returns
Query
<T
, never
>
an empty Query whose starting point is defined by a single CloudObject
instancesOf()
static instancesOf<T>(
model,
includeInheritance?,
source?): Query<T extends CloudObject ? T<T> : CloudObject, never>
Create a query starting from the instances of the specified model. By default, it does include the instances of the models that inherit from the given one.
Type Parameters
Type Parameter |
---|
T extends InstanceOrTag |
Parameters
Parameter | Type | Description |
---|---|---|
model | InstanceOrTag | Class <T > | tag/class of the model to find the instances of |
includeInheritance ? | boolean | if set to false, the result will not include instances of models that inherit from the given model. |
source ? | string | optional source of the data to answer the query A source can be the orchestrator ('server'), local ('self') or an external data source (Tag of a DBConnectorTag ) |
Returns
Query
<T
extends CloudObject
? T
<T
> : CloudObject
, never
>
a new query object starting from model instances
andReturn()
andReturn(): Query<T, R extends never ? T : R extends CloudObject[] ? [...R<R<R>>[], T] : [R, T]>
Add the current working set of nodes to the result.
Example: Query returning the instances of a model and the model itself
Query
.from(myModelTag).andReturn()
.follow(CloudObject.modelRel.getInverse()).andReturn()
.execute();
The result tuples are [modelCloudObject, instance1], [modelCloudObject, instance2], ...
Returns
Query
<T
, R
extends never
? T
: R
extends CloudObject
[] ? [...R<R<R>>[]
, T
] : [R
, T
]>
a new query object with the current level flagged to be returned.
back()
back(times?): Query<CloudObject, R>
The Query.back() function is used to move the cursor of a query backwards to the previous level.
This allows the query to start from the place where it was before a Query.follow() call,
but with a different relation. The times
parameter is optional and specifies the number of steps to go back.
If hops is not specified, the default value of 1 is used.
If a value equal to or smaller than 0 is specified, the output query is the same as the input query.
Example:
const people = [
\{ name: "Alice", children: ["Bob", "Carol"], siblings: ["David"] \},
\{ name: "Bob", children: ["Emily"], siblings: ["Alice", "Carol", "David"] \},
\{ name: "Carol", children: ["Frank"], siblings: ["Alice", "Bob", "David"] \},
\{ name: "David", children: ["Greg"], siblings: ["Alice", "Bob", "Carol"] \},
\{ name: "Emily", children: [], siblings: [] \},
\{ name: "Frank", children: [], siblings: [] \},
\{ name: "Greg", children: [], siblings: [] \}
];
// Create a new query starting from Alice
const aliceQuery = Query.from("Alice");
// Follow the "children" relation to get Alice's children (Bob, Carol)
const aliceChildrenQuery = aliceQuery.follow("children").andReturn();
// Go back to the previous level and follow the "siblings" relation to get Alice's siblings (David)
const aliceSiblingsQuery = aliceChildrenQuery.back().follow("siblings").andReturn();
// Execute the query, the output is:
Output: [ \{ sibling: 'David', child: 'Bob' \}, \{ sibling: 'David', child: 'Carol' \} ]
Parameters
Parameter | Type | Description |
---|---|---|
times ? | number |
Returns
Query
<CloudObject
, R
>
cast()
cast<S>(type): Query<S, R>
Cast the type of the instances in the current working set of nodes
Type Parameters
Type Parameter |
---|
S extends CloudObject |
Parameters
Parameter | Type | Description |
---|---|---|
type | Class <S > | cast type for CloudObjects |
Returns
Query
<S
, R
>
the
execute()
execute(options?): Promise<QueryResult<R extends never ? T : R extends CloudObject | CloudObject[] ? R<R> : never>>
Execute the query asynchronously on the datacloud and deletes it afterward.
In other words, one cannot call execute twice on the same Query
.
Parameters
Parameter | Type | Description |
---|---|---|
options ? | QueryOptions | options |
Returns
Promise
<QueryResult
<R
extends never
? T
: R
extends CloudObject
| CloudObject
[] ? R
<R
> : never
>>
promise resolving to query result or failing otherwise.
executeFromCache()
executeFromCache(): QueryResult<R extends never ? T : R extends CloudObject | CloudObject[] ? R<R> : never>
Execute synchronously the query on the local datacloud cache.
executeFromCache
can only be called once on a given Query
.
Returns
QueryResult
<R
extends never
? T
: R
extends CloudObject
| CloudObject
[] ? R
<R
> : never
>
query result of the execution on the local cache
filter()
filter(predicate): Query<T, R>
Define a filter operation on the current working set of nodes. It filters out instances that don't match the given Predicate
Parameters
Parameter | Type | Description |
---|---|---|
predicate | Predicate |
Returns
Query
<T
, R
>
a new query object with the new filter operation
follow()
follow<D>(relation, optional?): Query<D, R>
Instruct the query to follow a specified relation. This does not add any key-value pair to the result. (see Query.andReturn). This operation defines a new step in the path defined by our graph query.
Example: Find the model of a single object.
Query.from(myTag).follow(CloudObject.modelRel).andReturn()
Type Parameters
Type Parameter |
---|
D extends CloudObject |
Parameters
Parameter | Type | Description |
---|---|---|
relation | Relation <T , D > | relation to follow, specifies type and direction |
optional ? | boolean | whether or not the relation creates a mandatory path in the graph to be part of the result. |
Returns
Query
<D
, R
>
a new query object
followRecursively()
followRecursively<D>(
relation,
includeSelf?,
optional?): Query<D, R>
Follow a relation recursively, see Query.follow. The relation that is followed is automatically recursively followed. All nodes that are recursively followed are part of the same step in the path defined by this graph query.
Type Parameters
Type Parameter |
---|
D extends CloudObject |
Parameters
Parameter | Type | Description |
---|---|---|
relation | Relation <T , D > | relation to follow recursively, specifies type and direction. |
includeSelf ? | boolean | if a starting node includes itself when the relation loops on itself. (default: false) |
optional ? | boolean | whether or not the relation creates a mandatory path in the graph to be part of the result. (default: false) |
Returns
Query
<D
, R
>
a new query object
limit()
limit(max, offset?): Query<T, R>
Set the maximum number of tuples the executed query will return with an optional offset.
Only the last call to limit matters.
Example :
const queryLimited = query.limit(50).follow(myRel2).limit(100, 200).follow(myRel1);
// is equivalent to
const queryLimited2 = query.follow(myRel2).follow(myRel1).limit(100, 200);
queryLimited
, when executed, will return at most the 200th to the 299th (included) results.
Parameters
Parameter | Type | Description |
---|---|---|
max | number | maximum number of tuple to fetch from the final result |
offset ? | number | number of skipped tuples for the final result |
Returns
Query
<T
, R
>
new query with limit operation
observe()
observe(context, options?): Observable<QueryResult<R extends never ? T : R extends CloudObject | CloudObject[] ? R<R> : never>>
Get an observable to the current value of the QueryResult for this Query instance.
The observable gets the new value each time data modification in the datacloud changes the result of the query.
The observable gets completed automatically once the specified context is Context.onClear | cleared.
Parameters
Parameter | Type | Description |
---|---|---|
context | Context | Context to which the Observable is attached |
options ? | QueryOptions | options |
Returns
Observable
<QueryResult
<R
extends never
? T
: R
extends CloudObject
| CloudObject
[] ? R
<R
> : never
>>
Observable of QueryResult values
parse()
parse(): RootQueryPart
Returns
RootQueryPart
the query transformed as a tree of QueryPart. To be used by Data Source.
sortBy()
sortBy(property, order?): Query<T, R>
Sort the result tuples according to a property of a data type with a specified order. * For the sortBy operator to be properly defined, the following must be true:
- the property is defined on the instances that will be used for sorting.
- the instances on which the sorting property is defined must be part of the result,
i.e.,
andReturn()
has been called beforesortBy()
.
Only the last call to sortBy
matters as it will be the last comparator set on the query.
You should remove previous calls to sortBy
for the same query.
Example :
const sortQuery = Query
.fromInstances(myModel1).andReturn()
.sortBy(nameProperty)
.follow(rel1).andReturn()
.execute();
This query fetches instances of a model, flags them as first element of result tuples.
Then the query follows a relation to other instances and return them as second element of the result tuples.
sortBy
will sort the results according to the nameProperty
of the first element in the result tuples in
ascending order.
Parameters
Parameter | Type | Description |
---|---|---|
property | Property <any > | the property used for sorting |
order ? | Order | optional Order.ASC (default) or Order.DESC order |
Returns
Query
<T
, R
>
new query with sort operation