Commit a3aa5c22 authored by aleclofabbro's avatar aleclofabbro
Browse files

buildQueryDocumentSelection looks ok

parent 261cbb76
......@@ -75,8 +75,11 @@ type User implements Glyph {
# Main
input TopUserQueryInput {
User: UserQueryInput
}
type Query {
user(query: UserQueryInput): [User!]!
user(query: TopUserQueryInput, page: PageInput): [User!]!
}
input CreateUserInput {
......
......@@ -10,10 +10,9 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
context.$graph = {
qObj: {
__typename: 'Query',
query: {},
alias: 'Query',
directives: {},
traverse: [],
alias: 'Query',
select: [],
},
}
......@@ -30,20 +29,22 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
fieldName,
path: info.path,
parentQ,
args,
isTop,
})
if (!parentQ) {
throw new Error('defaultFieldResolver no parentQ')
}
if (isTop || ['_rel', '_subj', '_obj'].includes(fieldName)) {
parentQ.traverse.push(
...__typenames.map<GraphQueryObj>((__typename) => ({
traverse: [],
select: [],
directives: {},
query: args?.query[__typename],
__typename,
alias: `${info.path.key}`,
match: args?.query ? args?.query[__typename] : undefined,
page: args?.page,
select: [],
traverse: [],
directives: {},
}))
)
......
import { ObjectID } from 'mongodb'
import { GraphQuery, GraphQueryObj } from '../types'
export const buildQuery = (root: GraphQuery) => {
return _buildUnionQuery([root.qObj])
export const buildQueryDocumentSelection = (
root?: GraphQuery
): DocumentSelection | null | undefined => {
return root && buildDocumentSelection(root.qObj)
}
const _buildUnionQuery = (qObjs: GraphQueryObj[]) => {
// const groupedTraversesByAlias = traversingGQObj.traverse.reduce((_grouped, groupingQObj) => {
// const slots = _grouped[groupingQObj.alias] || (_grouped[groupingQObj.alias] = [])
// slots.push(groupingQObj)
// return groupingQObj
// }, {} as Record<string, GraphQueryObj[]>)
const stages: any[] = []
// const stages = [
// {
// $match: { $and: [{ __typename: { $in: qObjs.map((_) => _.__typename) } }, gqo.query.match] },
// },
// ...getTraverse,
// { $limit: gqo.query.page?.limit || 15 },
// ]
return qObjs.map((qObj) =>
qObj.traverse.reduce((resultStages, traversingGQObj) => {
if (!(traversingGQObj.select.length || traversingGQObj.traverse.length)) {
return resultStages
export const buildDocumentSelection = (qObj: GraphQueryObj): DocumentSelection | null => {
if (!(qObj.select.length || qObj.traverse.length)) {
return null
}
const documentValueFieldsSelections = qObj.select.reduce((_documentSelection, selection) => {
const valueField: ValueField = { fieldName: selection.field }
return {
..._documentSelection,
[selection.alias]: valueField,
}
}, {} as DocumentSelection)
const documentUnionLookupFieldSelections = qObj.traverse.reduce(
(_documentSelection, qObjSelection) => {
const _existingAlias = _documentSelection[qObjSelection.alias]
if (_existingAlias && 'fieldName' in _existingAlias) {
throw aliasConflictError(qObjSelection, qObj)
}
const select = buildDocumentSelection(qObjSelection)
if (!select) {
return _documentSelection
}
const unionLookupField: UnionLookupField =
_existingAlias ||
(_documentSelection[qObjSelection.alias] = { page: qObjSelection.page, lookups: [] })
return [...resultStages, ...stages]
}, [] as any[])
unionLookupField.lookups.push({
__typename: qObjSelection.__typename,
match: qObjSelection.match,
select,
})
return {
..._documentSelection,
[qObjSelection.alias]: unionLookupField,
}
},
{} as DocumentSelection
)
return {
...documentValueFieldsSelections,
...documentUnionLookupFieldSelections,
}
}
const aliasConflictError = (selection: GraphQueryObj, par: GraphQueryObj) => {
console.error(`A ValueField can't have same alias[${selection.alias}] as a UnionLookupField`, par)
return new Error(`A ValueField can't have same alias[${selection.alias}] as a UnionLookupField`)
}
export type ValueField = {
fieldName: string
}
export type LookupMap = { [alias: string]: UnionLookupField }
export type FieldLookup = {
__typename: string
match?: any
select: null | DocumentSelection
}
export type UnionLookupField = {
page?: {
limit?: number
after?: string | ObjectID
}
lookups: FieldLookup[]
}
export type DocumentSelection = {
[alias: string]: Field
}
export type Field = UnionLookupField | ValueField
......@@ -15,12 +15,10 @@ export type GraphQuery = {
export type GraphQueryObj = {
__typename: string
query: {
match?: any
page?: {
limit?: number
after?: string | ObjectID
}
match?: any
page?: {
limit?: number
after?: string | ObjectID
}
directives: Record<string, any>
select: Selection[]
......
......@@ -898,6 +898,27 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "TopUserQueryInput",
"description": null,
"fields": null,
"inputFields": [
{
"name": "User",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "UserQueryInput",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Query",
......@@ -912,7 +933,17 @@
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "UserQueryInput",
"name": "TopUserQueryInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "page",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "PageInput",
"ofType": null
},
"defaultValue": null
......
......@@ -129,6 +129,10 @@ export type User_RelArgs = {
page: Maybe<PageInput>;
};
export type TopUserQueryInput = {
User: Maybe<UserQueryInput>;
};
export type Query = {
__typename: 'Query';
user: Array<User>;
......@@ -136,7 +140,8 @@ export type Query = {
export type QueryUserArgs = {
query: Maybe<UserQueryInput>;
query: Maybe<TopUserQueryInput>;
page: Maybe<PageInput>;
};
export type CreateUserInput = {
......@@ -267,6 +272,7 @@ export type ResolversTypes = {
UserRelationQueryInput: UserRelationQueryInput;
UserRelation: ResolversTypes['Knows'] | ResolversTypes['Follows'];
User: ResolverTypeWrapper<Omit<User, '_rel'> & { _rel: Array<ResolversTypes['UserRelation']> }>;
TopUserQueryInput: TopUserQueryInput;
Query: ResolverTypeWrapper<RootValue>;
CreateUserInput: CreateUserInput;
Mutation: ResolverTypeWrapper<RootValue>;
......@@ -299,6 +305,7 @@ export type ResolversParentTypes = {
UserRelationQueryInput: UserRelationQueryInput;
UserRelation: ResolversParentTypes['Knows'] | ResolversParentTypes['Follows'];
User: Omit<User, '_rel'> & { _rel: Array<ResolversParentTypes['UserRelation']> };
TopUserQueryInput: TopUserQueryInput;
Query: RootValue;
CreateUserInput: CreateUserInput;
Mutation: RootValue;
......
......@@ -2,6 +2,8 @@ import { GraphQLServerOptions } from 'apollo-server-core/src/graphqlOptions'
import { ApolloServer } from 'apollo-server-express'
import express from 'express'
import { graphql, GraphQLSchema } from 'graphql'
import { Context } from '../gql'
import { buildQueryDocumentSelection } from '../gql-graph/mongo/queryBuilder'
type Cfg = {
httpPort: number
......@@ -16,9 +18,11 @@ export const start = ({ httpPort, schema }: Cfg) => {
const executor: GraphQLServerOptions['executor'] = async (requestContext) => {
console.log('executor')
const ctx = { c: 111 }
const ctx: Context = {}
const res = await graphql({ ...requestContext, contextValue: ctx })
console.dir({ 'executor res': res }, { compact: true, depth: 15, sorted: true })
console.dir({ 'executor $graph': ctx }, { compact: true, depth: 15, sorted: true })
console.dir({ 'executor res': res }, { depth: 15 })
console.dir({ 'executor $graph': ctx }, { depth: 15 })
const documentSelection = buildQueryDocumentSelection(ctx.$graph)
console.dir({ 'executor documentSelection': documentSelection }, { depth: 15 })
return Promise.resolve(res)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment