Skip to content

Instantly share code, notes, and snippets.

@ptpaterson
Last active December 26, 2021 15:09
Show Gist options
  • Save ptpaterson/82c01afc9b0ff624f96141a078b5ab54 to your computer and use it in GitHub Desktop.
Save ptpaterson/82c01afc9b0ff624f96141a078b5ab54 to your computer and use it in GitHub Desktop.
Template for building deeply nested FQL queries for FaunaDB
const baseQuery = q.Paginate(q.Match(q.Index(indexName), terms));
// or
// const baseQuery = q.Paginate(q.Collection(collectionName))
const expandedQuery = q.Map(baseQuery, (ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
{
// easy stuff
_id: q.Select(['id'], q.Var('ref')),
_ts: q.Select(['ts'], q.Var('instance')),
scalarField: q.Select(['data', 'scalarField'], q.Var('instance'), null),
scalarArray: q.Select(['data', 'scalarArray'], q.Var('instance'), []),
// embedded fields
embeddedField: q.Select(
['data', 'embeddedField'],
q.Var('instance'),
null
),
/* or */
selectedEmbeddedField: q.Let(
{
embeddedField: q.Select(
['data', 'embeddedField'],
q.Var('instance'),
null
)
},
q.If(q.Equals([q.Var('embeddedField'), null]), null, {
a: q.Select(['a'], q.Var('embeddedField'), null),
b: q.Select(['b'], q.Var('embeddedField'), null)
})
),
// one-to-one w/ reference in this collection
referenceField: q.Let(
{
ref: q.Select(['data', 'referenceField'], q.Var('instance'), null),
instance: q.Get(q.Var('ref'))
},
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
),
// multiple references in this collection
referenceArray: q.Map(
q.Select(['data', 'referenceArray'], q.Var('instance'), []),
(ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
),
// one-to-one with reference in other collection
indexByRef: q.Let(
{
page: Paginate(Match(Index('thing2ByThing1'), q.Var('instance'))),
ref: q.Select(['data', 0], q.Var('page')),
instance: q.Get(q.Var('ref'))
},
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
),
// one-to-many with reference in other collection
indexByRef: q.Map(
q.Paginate(Match(Index('thing2sByThing1'), q.Var('instance'))),
(ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
),
// many-to-many with link table
indexByRef: q.Map(
q.Paginate(Match(Index('thing2sByThing1s'), q.Var('instance'))),
(linkRef) =>
q.Let(
{
link: q.Get(q.Var('linkRef')),
ref: q.Select(['data', 'thing2'], q.Var('link')),
instance: q.Get(q.Var('ref'))
},
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
)
}
)
);
const baseQuery = q.Paginate(q.Match(q.Index(indexName), terms));
// or
// const baseQuery = q.Paginate(q.Collection(collectionName))
const expandedQuery = q.Map(baseQuery, (ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
// easy stuff
_id: q.Select(['id'], q.Var('ref')),
_ts: q.Select(['ts'], q.Var('instance')),
// one-to-one w/ reference in this collection
referenceField: q.Let(
{
ref: q.Select(['data', 'referenceField'], q.Var('instance'), null),
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
),
// multiple references in this collection
referenceArray: q.Map(
q.Select(['data', 'referenceArray'], q.Var('instance'), []),
(ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
)
),
// one-to-one with reference in other collection
indexByRef: q.Let(
{
page: Paginate(Match(Index('thing2ByThing1'), q.Var('instance'))),
ref: q.Select(['data', 0], q.Var('page')),
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
),
// one-to-many with reference in other collection
indexByRef: q.Map(
q.Paginate(Match(Index('thing2sByThing1'), q.Var('instance'))),
(ref) =>
q.Let(
{
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
)
),
// many-to-many with link table
indexByRef: q.Map(
q.Paginate(Match(Index('thing2sByThing1s'), q.Var('instance'))),
(linkRef) =>
q.Let(
{
link: q.Get(q.Var('linkRef')),
ref: q.Select(['data', 'thing2'], q.Var('link')),
instance: q.Get(q.Var('ref'))
},
q.Merge(
q.Var('instance'),
{
/* repeat above recursively */
/* `ref` and `instance` variables are scoped! */
}
)
)
)
}
)
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment