基于 GUID 的 HotChocolate GraphQL 过滤

Posted

技术标签:

【中文标题】基于 GUID 的 HotChocolate GraphQL 过滤【英文标题】:HotChocolate GraphQL filtering on GUID 【发布时间】:2021-11-25 19:59:38 【问题描述】:

我对 GraphQL 的了解非常有限,因为我仍在学习过程中。现在我偶然发现了一个问题,如果没有一些帮助,我无法自己解决。

我在服务中使用 HotChocolate。

我有一个 ConsumerProductCategory 类,GuidId,它的父类也是 ConsumerProductCategory(想想类别 > 子类别 > ...)

现在我想获取特定类别的子类别,在 linq 中你会写:

.Where(cat => cat.Parent.Id == id)

首先让我们从我们的类开始:

public class BaseViewModel : INode

    public virtual Guid Id  get; set; 



public class ConsumerProductCategory : BaseViewModel

    public ConsumerProductCategory()
    
    

    public string Name  get; set; 

    [UsePaging]
    [UseFiltering]
    [UseSorting]
    public List<ConsumerProduct> Products  get; set;  = new List<ConsumerProduct>();

    public ConsumerProductCategoryImage Image  get; set; 

    public ConsumerProductCategory Parent  get; set;  = null;

    public bool HasParent => this.Parent != null;

对象类型定义如下:

public class ConsumerProductCategoryType : ObjectType<ConsumerProductCategory>

    protected override void Configure(IObjectTypeDescriptor<ConsumerProductCategory> descriptor)
    
        descriptor
            .Name(nameof(ConsumerProductCategory));

        descriptor
            .Description("Categories.");

        descriptor
            .Field(x => x.Id)
            //.Type<UuidType>()
            .Type<IdType>()
            .Description($"nameof(ConsumerProductCategory) Id.");

        descriptor
            .Field(x => x.Name)
            .Type<StringType>()
            .Description($"nameof(ConsumerProductCategory) name.");

        descriptor
            .Field(x => x.Parent)
            .Description($"nameof(ConsumerProductCategory) parent category.");

        descriptor
            .Field(x => x.Products)
            .Description($"nameof(ConsumerProductCategory) products.");

        descriptor
           .ImplementsNode()
           .IdField(t => t.Id)
           .ResolveNode((context, id) => context.Service<IConsumerProductCategoryService>().GetByIdAsync(id));
    

获取“主要”类别的查询如下:

query GetAllCategories 
  consumerProductCategories(
    #request:  searchTerm: "2"
    first: 10
    after: null
    where:  hasParent:  eq: false  
    order: 
      name: ASC
    
  ) 
    nodes 
      id
      name
      image 
        url
        alt
      
    
    pageInfo 
      endCursor
      hasNextPage
    
  

这会返回这个结果:


  "data": 
    "consumerProductCategories": 
      "nodes": [
        
          "id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5",
          "name": "Category 1",
          "image": 
            "url": "https://picsum.photos/200",
            "alt": "Category 1 Image"
          
        ,
        
          "id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2NmZWI0YzNiMGQyNjQyOWI4MGU0MmQ1NGNjYWE1N2Q4",
          "name": "Category 2",
          "image": 
            "url": "https://picsum.photos/200",
            "alt": "Category 2 Image"
          
        ,
        
          "id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2I0MjhjYWE2NGMxNTQ4MTdiMjM1ZWFhZWU3OGRhYWYz",
          "name": "Category 3",
          "image": 
            "url": "https://picsum.photos/200",
            "alt": "Category 3 Image"
          
        
      ],
      "pageInfo": 
        "endCursor": "Mg==",
        "hasNextPage": false
      
    
  

我注意到的第一件事是 Id (Guid) 被更改为一些 base64 编码的字符串。

很奇怪,但如果我这样做:

query 
      node(
        id: "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5"
      ) 
        ... on ConsumerProductCategory 
          id
          name
        
        
      
    

这完全有效,结果:


  "data": 
    "node": 
      "id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5",
      "name": "Category 1"
    
  

但是,现在我想过滤 Parent.Id,

query GetSubcategories 
  consumerProductCategories(    
    first: 10
    after: null
    where:  parent:  id:  eq: "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2NmZWI0YzNiMGQyNjQyOWI4MGU0MmQ1NGNjYWE1N2Q4" 
    order: 
      name: ASC
    
  ) 
    nodes 
      id
      name
      image 
        url
        alt
      
      parent 
        id
      
    
    pageInfo 
      endCursor
      hasNextPage
    
  

这给出了一个错误,即我执行“eq”的字段类型不正确,这是有道理的,因为在数据中它实际上是一个 Guid。

结果:


  "errors": [
    
      "message": "The specified value type of field `eq` does not match the field type.",
      "locations": [
        
          "line": 5,
          "column": 31
        
      ],
      "path": [
        "consumerProductCategories"
      ],
      "extensions": 
        "fieldName": "eq",
        "fieldType": "UUID",
        "locationType": "UUID",
        "specifiedBy": "http://spec.graphql.org/June2018/#sec-Values-of-Correct-Type"
      
    
  ]

我明白为什么它会给我这个错误,但我不知道如何解决这个问题。

我在 Google 上到处找,但没有找到类似的问题,在 HotChocolate 的官方文档中,我真的找不到这个问题的解决方案。

谁能指出我正确的方向?

顺便说一句,将这些“自动生成”的 base64 字符串用作 Id 是一种好习惯,还是有某种方法可以指定不应该发生这种生成并实际返回 Guid?

提前致谢!

【问题讨论】:

【参考方案1】:

好的,我可以回答我自己的问题,基本上还不支持:github

我现在所做的只是在基类中添加第二个 Guid:

这会导致:

【讨论】:

以上是关于基于 GUID 的 HotChocolate GraphQL 过滤的主要内容,如果未能解决你的问题,请参考以下文章

HotChocolate 没有正确映射模型以输入

如何在 GraphQL HotChocolate 中实现订阅?

HotChocolate GraphQL 中的类型继承

HotChocolate 突变输入类型使用 int 而不是 ID

hotChocolate 中有没有办法记录在 IQueryable 上执行的查询

.NET HotChocolate 泛型类型分页