Open martypitt opened 1 week ago
This is a dump of interesting snippets we need to document / showcase in Taxi playground.
Add to this rough 'n' ready whenever we encounter something that we want to ensure is shown.
query FindSomeFilms( starring : PersonName ) {
find { Film[] } as {
title: Title
starring: filter(Actor[], (PersonName) -> PersonName == starring) as {
name : PersonName
}[]
}[]
}
.filterEach()
See can project using a named scope at the top level
find { Film[] } as (film:Film) -> {
movieName : film.title
}[]
see: a projection can refine whats in scope
model Film {
title : Title inherits String
cast : Actor[]
}
model Actor {
name : Name inherits String
}
find { Film } as (Actor[]) -> {
actorName : Name
filmTitle : Title // should be null, as it's out-of-scope on Actor
}[]
see: expressions in projection scopes can trigger discovery
:
find { Film } as (first(Actor[])) -> { // note that film has been removed from the scope...
title : Title //... so we expect this isn't discoverable.
starring : ActorName
}
Alternatively, with film in scope:
find { Film } as (Film, first(Actor[])) -> { // Here, Film is in scope...
title : Title // .. so this is knowable
starring : ActorName
}
find { Film[] } as (film:Film) -> {
title : FilmTitle
star : singleBy(film.cast, (Actor) -> Actor::ActorId, film.headliner) as (actor:Actor) -> {
name : actor.name
title : film.title
}
}[]
Note - if we make singleBy
an extension function (and we should), that gets simplified to:
find { Film[] } as (film:Film) -> {
title : FilmTitle
star : film.cast.singleBy((Actor) -> Actor::ActorId, film.headliner) as (actor:Actor) -> {
name : actor.name
title : film.title
}
}[]
see ProjectionsOnArraysTest.wtf:
type FilmId inherits Int
model Film {
title : FilmTitle inherits String
cast : CastId inherits Int
}
model Actor {
name : PersonName inherits String
}
model FilmCast {
actors : Actor[]
}
service Movies {
operation findFilm(FilmId):Film
operation getCast(CastId):FilmCast
}
Queried, loads from multiple services:
given { FilmId = 1 }
find { Film } as {
actor : first(Actor[]) as {
firstName : PersonName
}
}
query FindFilm( filmId : FilmId ) {
find { Film( FilmId == filmId ) }
}
see: can use a cast expression against a parameter in a given clause
type PersonId inherits String
type HumanId inherits String
query findPerson(personId : PersonId) {
given { humanId : HumanId = (HumanId) personId }
find { human : HumanId }
}
see: can use a cast expression in a given clause
type PersonId inherits String
type HumanId inherits String
given { humanId : HumanId = (HumanId) "123" }
find { human : HumanId }
In this example, we're filtering at the top level:
query FindSomeFilms( starring : PersonName ) {
find { Film[] } as (filter(Actor[], (PersonName) -> PersonName == starring)) -> {
name: PersonName
}[]
(see: can use a variable from a saved query in projection type expression
)
can also filter at the field level:
query FindSomeFilms( starring : PersonName ) {
find { Film[] } as {
title: Title
starring: filter(Actor[], (PersonName) -> PersonName == starring) as {
name : PersonName
}[]
}[]
}
(see: can use a variable from a saved query in a field projection
)
see: can populate a collection attrib with a value returned from a service
model Person {
@Id
id : PersonId inherits Int
name : PersonName inherits String
}
model Friend inherits Person
service Foo {
operation findAllPeople():PersonId[]
operation findPerson(PersonId):Person
operation findAllFriends(PersonId):Friend[]
}
query:
find { PersonId[] } as {
name : PersonName
friends : Friend[]
}[]
retrurns:
[
{
"name": "Doug",
"friends": [
{ "id": 1, "name": "Jimmy" },
{ "id": 2, "name": "Jack" }
]
}
]
see: given an array of discovered values, ids present in those arrays can look up attributes from other types
Given a movie:
model Movie {
title : MovieTitle inherits String
cast : Cast
}
model Cast {
actors : ActorId[]
}
And an actor:
model Actor {
@Id
id : ActorId
name : ActorName inherits String
}
Data is returned from seperate services:
service MovieService {
operation findAllMovies():Movie[]
operation findActor(ActorId):Actor
}
We can traverse the collections:
find { Movie[] } as {
movieTitle: MovieTitle
actors: ActorName[]
}
Here's that example as a Voyager example:
import {StubQueryMessageWithSlug} from "../../app/services/query.service";
export const example: StubQueryMessageWithSlug = {
"title": "Title goes here",
"slug": "slug-goes-here",
"query": {
"schema": ` // Given a movie:
type ActorId inherits Int
model Movie {
title : MovieTitle inherits String
cast : {
actors: ActorId[]
}
}
// And an actor:
model Actor {
@Id
id : ActorId
name : ActorName inherits String
}
// Data is returned from different APIs:
service MovieService {
operation findAllMovies():Movie[]
operation findActor(ActorId):Actor
}
`,
"query": `
// We can traverse these collections:
find { Movie[] } as {
movieTitle: MovieTitle
actors: ActorName[]
}[]
`,
"parameters": {},
"stubs": [
{
"operationName": "findAllMovies",
"response": " [ { \"title\" : \"The ducks take Manhattan\", \"cast\" : { \"actors\" : [1,2,3] } } ]"
},
{
"operationName": "findActor",
"response": "{ \"name\" : \"Mickey Mouse\" }"
}
]
}
}
|
service TweetService {
operation tweets():Stream<Tweet>
operation analytics():Stream<TweetAnalytics>
operation getUser(UserId):User
}
stream { Tweet | TweetAnalytics }
as {
id : MessageId
body : Message
views : ViewCount?
}[]
see: `can call mutation for each member of a stream``
// given a stream:
model UserUpdateMessage {
userId : UserId inherits String
message : StatusMessage inherits String
}
service UserUpdates {
stream updates: Stream<UserUpdateMessage>
}
// Elsewhere, User is defined:
model User {
id : UserId
name : UserName inherits String
}
service UserService {
operation getUser(UserId):User
}
// Finally, we want to persist updates, combining the message and user information:
parameter model RichUserUpdateMessage {
userId : UserId
name : UserName
message : StatusMessage
}
service UserService {
write operation storeUpdate(RichUserUpdateMessage):RichUserUpdateMessage
}
// The query:
stream { UserUpdateMessage }
call UserService::storeUpdate
// Will transform UserUpdateMessage into RichUserUpdateMessage, enriching it by calling getUser()
closed model
can not be constructed - only returned from a serviceparameter model
should be constructed when passing to a serviceclosed parameter model
can only be constructed when passing to a service closed parameter model Film {
@Id
filmId : FilmId
title : Title
}
@HazelcastService(connectionName = "notUsed")
service HazelcastService {
@UpsertOperation
write operation upsert(Film):Film
@DeleteOperation(mapName = "films")
write operation deleteAll()
@DeleteOperation(mapName = "films")
write operation deleteByKey(FilmId):Film
table films : Film[]
}
convert()
see can convert from one type to another using convert
[[
Converts the provided source into the target type reference.
Conversions are performed locally, using only the data provided in source - ie.,
no services or graph searches are performed.
This method is less powerful than using a standard projection (eg., A as B), because:
- Only the exact facts passed in the source are considered
- No graph searches or remote invocations are performed
As a result, it's also more performant.
]]
declare function <T> convert(source: Any, targetType: lang.taxi.Type<T>): T"""
model Person {
name : FirstName inherits String
age : PersonAge inherits String
}
model Dude {
knownBy : FirstName
}
model Thing {
person : Person
dude : convert(this.person, Dude)
}
see: generates the correct fields with excluded fields
...
and ... except
:
find { Person } as {
name : FirstName
address : Address as {
isOddNumbered : Boolean
house : HouseNumber
... except {secretCode}
}
... except {secretAge}
}
find { Person } as {
name, // reads name from Person
address // etc
}
These examples from TaxiQlServiceRestrictionsSpec
:
using
: closed model Film {
title : Title inherits String
}
service FilmService {
operation getFilms():Film[]
operation getBlockbusters():Film[]
}
find { Film[] }
using { FilmService::getFilms }
service NetflixService {
operation getFilms():Film[]
operation getBlockbusters():Film[]
}
find { Film[] }
using { FilmService::getBlockbusters , FilmService::getFilms, NetflixService }
find { Film[] }
excluding { FilmService::films }
Add comments to this issue to capture demos that we need to build. We'll review, then split them out into seperate issues