Hot Chocolate + Mongo:当我只询问参考 ID 时无需额外调用

Hot Chocolate + Mongo: No additional call when I ask only for referene id

假设我在 mongo 中有以下文件:

产品:

产品模板:

我将产品映射到以下架构:

product {
 ...
 productTemplate {
  id,
  ...
 }
 ...
}
  1. 我想避免在只询问 product { productTemplate {id}} 时进行额外的调用,因为此信息在产品实体中。可能吗?
  2. 我只想从 mongo 获取具有 productTemplateId 的产品而不是整个文档。这很重要,因为我有大约 100 req/s。是否可以仅针对文档中的预期字段询问 mongo?

这是我的部分代码:

public class ProductType : ObjectType<ProductDocument>
{
    protected override void Configure(IObjectTypeDescriptor<ProductDocument> descriptor)
    {
        descriptor.BindFieldsExplicitly();
        descriptor.Name("Product");            
        descriptor.Field("productTemplate")
            .Type<ProductTemplateType>()
            .ResolveWith<ProductTemplatesResolver>(r => r.GetProductTemplate(default!, default!, default));
    }
}

public class ProductTemplatesResolver
{
    public Task<ProductTemplateDocument> GetProductTemplate([Parent] ProductDocument product,
        ProductTemplatesBatchDataLoader loader,
        CancellationToken cancellationToken)
    {
        return loader.LoadAsync(product.ProductTemplateId, cancellationToken);
    }
}

public class ProductTemplatesBatchDataLoader : BatchDataLoader<int, ProductTemplateDocument>
{
    private readonly ProductsDbContext _dbContext;
    
    public ProductTemplatesBatchDataLoader(IBatchScheduler batchScheduler, ProductsDbContext dbContext, DataLoaderOptions? options = null) : base(batchScheduler, options)
    {
        _dbContext = dbContext;
    }

    protected override async Task<IReadOnlyDictionary<int, ProductTemplateDocument>> LoadBatchAsync(IReadOnlyList<int> keys, CancellationToken cancellationToken)
    {
        var pts = await _dbContext.ProductTemplates
            .AsQueryable()
            .Where(x => keys.Contains(x.Id))
            .ToListAsync(cancellationToken);

        return pts.ToDictionary(x => x.Id, x => x);
    }
}

谢谢

您可以通过 IResolverContext GetSelections 获取所选字段

public class ProductTemplatesResolver
{
    public Task<ProductTemplateDocument> GetProductTemplate(
        [Parent] ProductDocument product,
        IResolverContext context,
        ProductTemplatesBatchDataLoader loader,
        CancellationToken cancellationToken)
    {
        var selectedFields = context.GetSelections((ObjectType)context.Selection.Field.Type);
        if (selectedFields.Count == 1 && selectedFields[0].Field.Name == "id")
        {
            return new ProductDocument(product.TemplateId);
        }
        return loader.LoadAsync(product.ProductTemplateId, cancellationToken);
    }
}