Hot Chocolate + Mongo:当我只询问参考 ID 时无需额外调用
Hot Chocolate + Mongo: No additional call when I ask only for referene id
假设我在 mongo 中有以下文件:
产品:
- ...
- productTemplateId
- ...
产品模板:
- id
- ...
我将产品映射到以下架构:
product {
...
productTemplate {
id,
...
}
...
}
- 我想避免在只询问
product { productTemplate {id}}
时进行额外的调用,因为此信息在产品实体中。可能吗?
- 我只想从 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);
}
}
假设我在 mongo 中有以下文件:
产品:
- ...
- productTemplateId
- ...
产品模板:
- id
- ...
我将产品映射到以下架构:
product {
...
productTemplate {
id,
...
}
...
}
- 我想避免在只询问
product { productTemplate {id}}
时进行额外的调用,因为此信息在产品实体中。可能吗? - 我只想从 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);
}
}