Comments (9)
Aggregate
You can now aggregate horizon queries together like this:
let horizon = Horizon()
let aggregated = horizon.aggregate({
owner: horizon('people').find('bob'),
pet: horizon('animals').find('spot'),
related: {
friends: horizon('people').findAll({friendOf: 'bob'}).limit(10),
petFriends: horizon('animals').findAll({friendOf: 'spot'}).limit(10),
},
someConstant: "Always have this here",
petsAndOwners: [ hz('pets'), hz('owners') ] // this is nonsensical, but you know, example
})
You can now call .fetch()
or .watch()
on the aggregate, and it will do what you expect. With .watch()
, it will internally emit a new document any time any sub-query receives a change, it caches the results of all other subqueries and re-emits them.
Aggregates can be composed of several things:
- Objects, like in the example above
- Arrays:
aggregate([hz('foo'), hz('bar')])
will result in an array that has the results of thefoo
andbar
tables flattened into one. There's no guarantee on ordering. - Literals:
null
,numbers
,strings
,boolean
s,Date
s andArrayBuffer
s can be put into aggregates and they'll be emitted as-is in the final datastructure. (Arrays and objects that contain literals will be emitted as-is, so this works as you'd expect:hz.aggregate([1, true, 'bob']).fetch()
->[1, true, 'bob']
- Horizon queries:
hz.aggregate(hz('foo').find(2))
is equivalent tohz('foo').find(2)
- Observables: they'll be emitted with whatever behavior they already have, so there's no difference for them between
.fetch()
and.watch()
. This can be helpful if you want to update a counter or the like:
hz.aggregate({
counter: Observable.timer(0, 1000),
someQuery: hz('foo').find('bar'),
}).watch().subscribe({ next(x){ console.log(x) }})
Every second (or whenever the someQuery
gets a change), the entire datastructure will be re-emitted with an incremented counter.
You can also nest aggregates, like:
hz.aggregate({
foo: hz.aggregate({ ... })
})
But this isn't super useful, since it's equivalent to just doing:
hz.aggregate({
foo: { ... }
})
Model
You can also parameterize aggregates using the model
method. It's fairly simple and just allows a convenient syntax for creating templates for aggregates:
const MyModel = hz.model((a, b, c) => {
return {
foo: hz('foo').find(a),
bar: hz('bar').find(b),
baz: hz('baz').find(c),
}
})
// Sometime later, use it
var modelA = MyModel(1, 2, 3)
var modelB = MyModel(2, 3, 4)
modelInstance.fetch().subscribe(x => console.log(x))
You can do anything you can do with aggregates here, but it's worth mentioning you can also nest models (which will seem maybe more useful than nesting aggregates, even though it's equivalent):
const Pet = hz.model(petId => hz('pets').find(petId)) // note you can aggregate a bare query
const Owner = hz.model( ownerId => hz('owners').find(ownerId) )
const PetAndOwner = hz.model((petId, ownerId) => {
pet: Pet(petId),
owner: Owner(ownerId),
})
var marcAndSkyla = PetAndOwner('skyla', 'marc')
var dalanAndRes = PetAndOwner('res', 'dalan')
marcAndSkyla.fetch()
dalanAndRes.watch()
from horizon-docs.
Sounds good, I'll change it. We already have a way to union queries anyway (hz('foo').fetch().merge(hz('bar').fetch())
), so a special syntax for it isn't really warranted probably.
I would like to take this moment to grumble that it's more work for me
from horizon-docs.
Marshall also made Promises work in aggregates, so that's allowed now too
from horizon-docs.
Arrays: aggregate([hz('foo'), hz('bar')]) will result in an array that has the results of the foo and bar tables flattened into one. There's no guarantee on ordering.
What's the behavior .aggregate([1, hz('bar')])
?
What about.aggregate([[1, 2], hz('bar')])
?
What about.aggregate([[1, 2], hz('bar'), hz('foo')])
?
What about.aggregate([[1, 2], hz('bar'), [3, 4], hz('foo')])
?
Is there any way to get back an array containing two arrays each of which comes from a Horizon query (i.e. to get [[foo1, foo2, ...], [bar1, bar2, ...]]
instead of [foo1, bar1, foo2, bar2, ...]
)?
(Also, are we super attached to the fact thathorizon.aggregate([FOO, BAR])
does an implicit union of the two streams? That seems kind of wacky to me, especially because it looks like we aren't implicitly unioning non-Horizon objects when they're put inside the same syntax. I would expect hz.aggregate([FOO, BAR])
to give me the [[foo1, foo2, ...], [bar1, bar2, ...]]
shape. Another option would be to make hz.aggregate([FOO, BAR])
return [[foo1, foo2, ...], [bar1, bar2, ...]]
and hz.aggregate(FOO, BAR)
return [foo1, bar2, foo2, bar2, ...]
.)
from horizon-docs.
Actually, thinking about it more, it seems kinda bad that hz.aggregate([FOO, BAR])
does an implicit union. For everything else we seem to have the property the hz.aggregate(f(FOO))
is analogous to FOO.fetch().subscribe(x => hz.aggregate(f(x)))
(ignoring the updating). Doing an implicit union for Horizon queries but not for other objects breaks that property.
from horizon-docs.
So just so I'm clear, this is a method on the Horizon
object, not Collection
(because it operates on multiple collections).
from horizon-docs.
Right, the horizon toplevel object itself
from horizon-docs.
So. Freaking. Great.
from horizon-docs.
(Since this is merged into the horizon-2.0
branch I'm closing this issue.)
from horizon-docs.
Related Issues (20)
- Upgrade docker-compose files to v2 of the docker-compose file spec HOT 8
- Document integration with specific frameworks (React etc.) HOT 2
- Users doc misleading
- cookbook entry: subscribing to changing data
- Horizon 2.0 docs checklist HOT 27
- Document `Collection.update`, `Collection.insert` and correct existing write commands
- Clarify client constructor host option
- .filter() listed twice in Observable's methods. HOT 1
- We need a guide on "Deploying Horizon"
- New page about Horizon client packaging HOT 2
- Section headers should be clickable to put the fragment in the URL path
- Document admin user requirement
- Permissions only mentions `.find` once but it isn't clear if using `.findAll` covers `.find`? HOT 2
- Auth documentation needs to show boilerplate on how to handle connections by unauth'd and auth'd users
- Embedding docs incorrectly uses `_reql_conn` as a property of the server module HOT 2
- Document how to use JWT generated using CLI
- horizon js can not access rethinkdb in port 28025 without --dev flag . Error : action not permitted .
- Docs at http://horizon.io/docs/auth/ don't say what callback URL to use HOT 8
- Include section in FAQ on why full ReQL queries aren't supported in Horizon
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from horizon-docs.