-
Notifications
You must be signed in to change notification settings - Fork 124
Description
Union operator
We want a way to union two or more collections so that they can be used as a single source within a live query.
There needs to be both static and dynamic union operators, with the latter mutable.
Use cases:
- Sharding data across multiple collections for smaller sync
- Dynamically creating datasets from multiple sources - such as a feed reader with a collection for each feed and then a union of all of them for a "all" view.
Static union operator
q
.from({
source: union(collection1, collection2)
})
.where(({ source }) => gt(source.value, 1))
Implementation
This is the simplest to implement, it can map to a concat operator in the D2 graph. However, there is complexity if we want to use any of the indexes in the underlying collections. A first version could just de-optimise the query to use a full scan and then we can add optimizations later.
Dynamic union operator with manual mutation
Often a union may not be static, but something that you want to be able to add and remove sources from without having to restart the live query.
// Union returns a set like object
const sourcesUnion = union(collection1)
q
.from({
source: sourcesUnion
})
.where(({ source }) => gt(source.value, 1))
sources.add(collection2)
// do something
sources.remove(collection1)
Implementation
This is more complex to implement, we need to be able to mutate the set as the results of the live query change. We would need to maintain some sort of history of what has been sent in order to pass in the deletes when a source is removed.
Dynamic union operator constructed from a live query itself
An additional unionFromLiveQuery function that takes a live query, and a function that takes a results from that live query, and returns a collection. This wraps the union function, mutating the set as the results of the live query change.
const sourcesUnion = unionFromLiveQuery(
(q) => q
.from({
rssFeed: rssFeedsCollection
}),
({ rssFeed }) => createCollection(
rssFeedsCollectionOptions({
url: rssFeed.url
})
)
)
q
.from({
source: sourcesUnion
})
.where(({ source }) => gt(source.value, 1))
Implementation
This is a little simpler to implement as its really just a wrapper around the union function with mutations driven from the live query.