Closed alexisvincent closed 8 years ago
Although your proposal does solve the problem of readability, you lose the ability to apply any modifiers to the nested query. That would be very limiting.
An alternative to this would be to have a way to alias models. Something like:
import { model, alias } from 'modelizr'
const user = model('users')
const employer = alias(user, "employer")
const author = alias(user, "author")
query(
event(
book(
author()
),
employer()
)
)
You don't loose the ability to apply modifier, however as you say, the expressivity is limited. Model aliases would make the query nice, however you run into issues with namespace conflicts if a field name refers to two different type definitions. Also, it would be painful to alias everything every time. Nested queries such as the one below are common. However. I can't really think of a solution...
Perhaps a more manageable instant fix is allowing pre modifiers. So that you could do something like this.
import { query } from 'modelizr'
import { event, organization, user, book } from './schema.js'
query(
event(
organisation.as('company',
user.as('founder',
book.as('favoriteBook',
user.as('author',
company.as('employer',
user.as('father')
)
),
book.as('inspiredBy',
user.as('author',
user.as('guardian',
user.as('mother')
)
)
)
)
)
)
)
)
Also consider:
query(
event(
organisation('company',
user('founder',
book('favoriteBook',
user('author',
company('employer',
user('father')
)
),
book('inspiredBy',
user('author',
user('guardian',
user('mother')
)
)
)
)
)
)
)
)
And by extension (for query parameters)
query(
event(
organisation('company', {id: 5}
user('founder',
book('favoriteBook', {limit: 10, offset: 3}
user('author',
company('employer',
user('father')
)
),
book('inspiredBy',
user('author',
user('guardian',
user('mother')
)
)
)
)
)
)
)
)
query( event( organisation('company', {id: 5} user('founder', book('favoriteBook', {limit: 10, offset: 3} user('author', company('employer', user('father') ) ), book('inspiredBy', user('author', user('guardian', user('mother') ) ) ) ) ) ) ) )
I like this syntax. It fits much better with the current API.
:) Cool Stuffs. This is the best that I can think of at this point in time. Still conflates type system and query but the query language feels closer to graphql.
Something that can also be noted here is that in this example, the model is really only providing a function syntax. Something such as the following would be functionally equivalent.
query(
event(
q('company', {id: 5}
q('founder',
q('favoriteBook', {limit: 10, offset: 3}
q('author',
q('employer',
q('father')
)
)
)
)
)
)
)
if we then made the function q automatically curried we can do the following.
company = q('company')
founder = q('founder')
favoriteBook = q('favoriteBook')
author = q('author')
employer = q('employer')
father = q('father')
query(
event(
company({id: 5}
founder(
favoriteBook({limit: 10, offset: 3}
author(
employer(
father()
)
)
)
)
)
)
)
While on surface this looks the same as your type alias proposal from earlier, it is fundamentally different. As something like company()
is really just an alias to a string not an actual type. And so the namespace problem mentioned in the second comment, would not apply.
I'm trying to explore ideas and their implications, I'm not necessarily advocating the above design.
Personally I think the syntax below is the most practical.
query( event( organisation('company', {id: 5} user('founder', book('favoriteBook', {limit: 10, offset: 3} user('author', company('employer', user('father') ) ), book('inspiredBy', user('author', user('guardian', user('mother') ) ) ) ) ) ) ) )
Something that can also be noted here is that in this example, the model is really only providing a function syntax. Something such as the following would be functionally equivalent.
Not quite true. It is also providing a schema and defined model relationships. So your following example would not be equivalent.
Your second proposal would require a complete rewrite of the api as models()
do not return themselves.
Personally I think the syntax below is the most practical.
Agreed.
Your second proposal would require a complete rewrite of the api as models() do not return themselves.
Not quite true I suppose. Could have a type check for a string and return the model as a function.
Not quite true. It is also providing a schema and defined model relationships. So your following example would not be equivalent.
This can be inferred from the root type. You don't need the model schema.
Not in the current spec. So at the current state of modelizr, you do need to use specific models.
Not in the current spec. So at the current state of modelizr, you do need to use specific models.
Sure, this was more of an experiment with a query language ;)
The current 'query language' conflates queries with the type system and is difficult to read due to field names (as mutator/modifier) being at the bottom. This could be simplified by using a json tree and leveraging the type system. Thought I would give a proper example after our discussion earlier.
current implementation
proposal
and alternatively for the adventurous