我具有当前的解析器功能:
/********************
* recipe.resolver.ts
********************/
import { Args, Info, Query, Resolver, } from '@nestjs/graphql';
import { Recipe } from './recipe.model';
import { RecipeService } from './recipe.service';
import { FindAllArgs } from './entities/shared/dto/find-all.args';
@Resolver(of => Recipe)
export class RecipeResolver {
constructor(private readonly recipeService: RecipeService) {}
@Query(returns => [Recipe])
async recipes(
@Args() findAllArgs: FindAllArgs,
@Info() info,
): Promise<Recipe[]> {
return this.recipeService.findAll(info, findAllArgs);
}
}
它利用了当前的服务功能:
/********************
* recipe.service.ts
********************/
import * as mongo from 'mongodb';
import { Injectable } from '@nestjs/common';
import { Recipe } from './recipe.model';
import { InjectCollection } from 'nest-mongodb';
import { FindAllArgs } from './entities/shared/dto/find-all.args';
@Injectable()
export class RecipeService {
constructor(@InjectCollection('Recipe') private readonly recipeCollection: mongo.Collection) {}
async findAll(info, findAllArgs: FindAllArgs): Promise<Recipe[]> {
const queryAstFields = info.fieldNodes[0].selectionSet.selections;
let idAbsent = true;
const requestedFields = queryAstFields.reduce(
(obj, item) => {
const fieldName = item.name.value;
if (fieldName === 'id') {
idAbsent = false;
}
return Object.assign(obj, { [fieldName]: true })
}, {});
if (idAbsent) {
requestedFields._id = false;
} else {
delete requestedFields.id;
}
return this.recipeCollection.find({}, {projection: requestedFields, ...findAllArgs}).toArray();
}
}
}
我的args DTO看起来像这样:
/********************
* find-all.args.ts
********************/
import { Min } from 'class-validator';
import { ArgsType, Field, Int } from 'type-graphql';
import { FindOneOptions } from 'mongodb';
@ArgsType()
export class FindAllArgs implements FindOneOptions {
@Field(type => Int, {defaultValue: 0})
@Min(0)
skip?: number;
@Field(type => Int, {defaultValue: 0})
@Min(0)
limit?: number;
}
如您所见,我已经在尝试使用projection
函数中的options参数中的MongoDB的limit
,skip
和find()
。但是,我最近了解到graphql-to-mongodb
npm package。看来它完全可以实现我正在做的事情。我想使用它;但是,我不确定如何将其合并到NestJS围绕GraphQL的解析器和type-graphql's
参数的方式中。
我假设我必须在解析器中使用它,但是它具有getMongoDbQueryResolver和getGraphQLQueryArgs,并且我不确定如何添加它们。
存储库中有一个Apollo Example,但我不确定如何实现。
我以为我会尝试手动重做ArgsType
中的所有内容,但是我遇到了为非number
,string
或{ {1}};已经具有标量类型的那些。
boolean
我知道我可以定义自定义标量,但这是解决问题的方法吗?我可以找到的唯一自定义标量示例是/********************
* find-all.args.ts
********************/
import { Min } from 'class-validator';
import { ArgsType, Field, Int } from 'type-graphql';
import { FindOneOptions } from 'mongodb';
@ArgsType()
export class FindAllArgs implements FindOneOptions {
@Field(type => Int, { defaultValue: 0, description: 'Sets the limit of documents returned in the query.' })
@Min(0)
limit?: number;
// sort?: any[] | object; <-- What to do here?
// projection?: object; <-- What to do here?
@Field(type => Int, { defaultValue: 0, description: 'Set to skip N documents ahead in your query (useful for pagination).' })
@Min(0)
skip?: number;
// hint?: object; <-- What to do here?
@Field({ defaultValue: false, description: 'Explain the query instead of returning the data.' })
explain?: boolean;
@Field({ defaultValue: false, description: 'Specify if the cursor can timeout.' })
timeout?: boolean;
@Field({ defaultValue: false, description: 'Specify if the cursor is tailable.' })
tailable?: boolean;
@Field(type => Int, { defaultValue: 1000, description: 'Set the batchSize for the getMoreCommand when iterating over the query results.' })
@Min(0)
batchSize?: number;
@Field({ defaultValue: false, description: 'Only return the index key.' })
returnKey?: boolean;
@Field({ nullable: true, description: 'Set minimum index bounds.' })
@Min(0)
min?: number;
@Field({ nullable: true, description: 'Set maximum index bounds.' })
@Min(0)
max?: number;
@Field({ defaultValue: false, description: 'Show disk location of results.' })
showDiskLoc?: boolean;
@Field({ nullable: true, description: 'You can put a $comment field on a query to make looking in the profiler logs simpler.' })
comment?: string;
@Field({ defaultValue: false, description: 'Return document results as raw BSON buffers.' })
raw?: boolean;
@Field({ defaultValue: true, description: 'Promotes Long values to number if they fit inside the 53 bits resolution.' })
promoteLongs?: boolean;
@Field({ defaultValue: true, description: 'Promotes BSON values to native types where possible, set to false to only receive wrapper types.' })
promoteValues?: boolean;
@Field({ defaultValue: false, description: 'Promotes Binary BSON values to native Node Buffers.' })
promoteBuffers?: boolean;
// readPreference?: ReadPreferenceOrMode; <-- What to do here?
@Field({ defaultValue: false, description: 'Specify if the cursor should return partial results when querying against a sharded system.' })
partial?: boolean;
@Field(type => Int, { nullable: true, description: 'Number of milliseconds to wait before aborting the query.' })
@Min(0)
maxTimeMS?: number;
}
的示例,因此必须定义returnTypeFunction,而且我不知道如何告诉它返回相同的对象。
这是提供的示例:
Date
例如,如何将/********************
* date.scalar.ts
********************/
import { CustomScalar, Scalar } from '@nestjs/graphql';
import { Kind } from 'graphql';
@Scalar('Date', type => Date)
export class DateScalar implements CustomScalar<number, Date> {
description = 'Date scalar type; Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.';
parseValue(value: number): Date {
return new Date(value); // value from the client
}
serialize(value: Date): number {
return value.getTime(); // value sent to the client
}
parseLiteral(ast: any): Date {
if (ast.kind === Kind.INT) {
return new Date(ast.value);
}
return null;
}
}
转换为标量类型,例如示例中的类型?