Skip to main content
Version: Next

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.

Index

Constructors

constructor

  • new Query<T, R>(): Query<T, R>

Methods

andReturn

  • andReturn(): Query<T, R extends never ? T : R extends CloudObject[] ? [...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[], T] : [R, T]>

    a new query object with the current level flagged to be returned.

back

  • 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 &lt;= 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

    • optionaltimes: number

    Returns Query<CloudObject, R>

cast

  • Cast the type of the instances in the current working set of nodes


    Type parameters

    Parameters

    • type: Class<S>

      cast type for CloudObjects

    Returns Query<S, R>

    the

execute

  • Execute the query asynchronously on the datacloud and deletes it afterward. In other words, one cannot call execute twice on the same Query.


    Parameters

    Returns Promise<QueryResult<R extends never ? T : R extends CloudObject | CloudObject[] ? R : never>>

    promise resolving to query result or failing otherwise.

executeFromCache

  • 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 : never>

    query result of the execution on the local cache

filter

  • Define a filter operation on the current working set of nodes. It filters out instances that don’t match the given Predicate


    Parameters

    Returns Query<T, R>

    a new query object with the new filter operation

follow

  • follow<D>(relation: Relation<T, D>, optional?: boolean): 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

    Parameters

    • relation: Relation<T, D>

      relation to follow, specifies type and direction

    • optionaloptional: 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: Relation<T, D>, includeSelf?: boolean, optional?: boolean): 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

    Parameters

    • relation: Relation<T, D>

      relation to follow recursively, specifies type and direction.

    • optionalincludeSelf: boolean

      if a starting node includes itself when the relation loops on itself. (default: false)

    • optionaloptional: 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: number, offset?: number): 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

    • max: number

      maximum number of tuple to fetch from the final result

    • optionaloffset: number

      number of skipped tuples for the final result

    Returns Query<T, R>

    new query with limit operation

observe

  • 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 cleared.


    Parameters

    Returns Observable<QueryResult<R extends never ? T : R extends CloudObject | CloudObject[] ? R : never>>

    Observable of QueryResult values

parse


  • Returns RootQueryPart

    the query transformed as a tree of QueryPart. To be used by Data Source.

sortBy

  • 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 before sortBy().

    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

    Returns Query<T, R>

    new query with sort operation

staticfollowRule

  • Create a query starting from a specific root instance, then following relations based on a rule constraint.


    Type parameters

    Parameters

    • 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

    • optionalsource: string

      The tag of the source responsible for executing the query

    • optionaloptions: ImplicitQueryOption

      options

    Returns Observable<QueryResult<T extends CloudObject ? T : CloudObject>>

staticfrom

  • 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

    Parameters

    • tag: T

      tag of the CloudObject the query is starting from

    • optionalsource: string

      optional source of the data to answer the query

    Returns Query<T extends CloudObject ? T : CloudObject, never>

    an empty Query whose starting point is defined by a single CloudObject

staticfromTag

  • 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

    Parameters

    • tag: string

      tag of the CloudObject the query is starting from

    • dataType: InstanceOrTag | Class<T>

      data type of the tag CloudObject.

    • optionalsource: 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

staticinstancesOf

  • 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

    Parameters

    • model: InstanceOrTag | Class<T>

      tag/class of the model to find the instances of

    • optionalincludeInheritance: boolean

      if set to false, the result will not include instances of models that inherit from the given model.

    • optionalsource: 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 : CloudObject, never>

    a new query object starting from model instances