Create a ordered set of heterogenous documents

Is there an easy pattern for creating an ordered, paginated set of heterogenous documents from different collections in FQLv10? I have a set of collections whose documents all have a foreign key to a common document in the accounts collection. E.G. charges, payments, invoices, etc.

On the front end I want to build an account timeline that shows each of these items in descending order based on time. It would be nice to be able to provide an API on the back end that could provide a single, paginated, heterogenous set of these different documents already sorted rather than paginate through multiple different collections and build the heterogenous set client side.

You can concatenate multiple sets together, but that would paginate one full set after another

Bits.all().concat(Bobs.all())

One Collection as a discriminated union

If you model include several types that are variations on a thing, then you might consider putting all of the data in a single collection, and using a field to discriminate between types. You could then index on that discriminator if you need to list items of a single type only. This is especially nice if all of the types implement a common interface, such as having a created_at field which could be used to sort all of the various types in order.

Once schema enforcement is enabled, you will still be able to define documents as discriminated unions in this way.

let ChargeFragment  = x => x { /* project desired fields */ }
let PaymentFragment = x => x { amount, status, method, /* etc. */ }
let InvoiceFragment = x => x { /* ... */ }

FinancialItem.all().map(x => {
  if (x isa Charge) {
    ChargeFragment(x)
  } else if (x isa Payment) {
    PaymentFragment(x)
  } else if (x isa Invoice) {
    InvoiceFragment(x)
  }
})

Relationship with a common Collection

If the collections need to stay separate, you can create a relation with an additional collection that stores the sorted field, and a reference to one of any of the other collections.

FeedItem.all__myField_asc().map(x => {
  let discriminator = x._type
  if (discriminator == "Charge") {
    ChargeFragment(x)
  } else if (discriminator == "Payment") {
    PaymentFragment(x)
  } else if (discriminator == "Invoice") {
    InvoiceFragment(x)
  }
})

I thought there was a way in v4 to have an index use multiple sources? Is there no such method in v10? I would need to use the Relationship with a common Collection solution, as these objects need to be separate collections. However, having an index manage that rather than adding extra logic to create/update/delete refs when things change is preferred.

In v4, you can indeed specify multiple Collections as a source. This was dropped in the initial version of v10 to enabled some optimizations on the back end and also the new syntax.

It is on the roadmap to add indexes with multiple collections as a source to v10. We’re still working on what that will look like.