本文介绍了GraphQL - 如何过滤层次结构?(“上个月订购了小玩意儿的客户")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设 Customer -(hasMany)-> 的类型层次结构;订单 -(hasMany)->订单行

像这样:

Customer {
    Name
    Orders [
        {
            OrderId
            Date
            OrderLines [
                { 
                    ItemCount
                    ItemName
                }
            ]
        }
    ]
}

我想查询整个树,并对树中任何级别的属性进行过滤.

I want to query for this whole tree, and filter on properties at any level in the tree.

例如:获取所有订购gizmos"的客户.

For instance: Get all customers who ordered 'gizmos'.

这是我尝试过的:在层次结构的每个级别,我指定可选参数,这些参数将根据该级别可用的属性进行过滤:

This is what I tried: at each level of the hierarchy, I specify optional arguments that would filter based on the properties available at that level:

Customer (Name) {
    Name
    Orders (OrderId, Date) [
        {
            OrderId
            Date
            OrderLines (ItemCount, ItemName) [
                { 
                    ItemCount
                    ItemName
                }
            ]
        }
    ]
}

GraphQL 需要我定义如何解析层次结构中的每种类型,因此在解析时,我会根据查询中的参数进行过滤.

GraphQL needs me to define how to resolve each type in the hierarchy, so when resolving, I filter based on the arguments in the query.

但是如果我只在深层指定一个过滤器呢?ItemName : 'gizmo'

假设系统中只有一个包含 Gizmo 的订单行,我希望得到这样的响应:

Assuming there's only one order line in the system containing a gizmo, I would expect to get a response like this:

[{
    Name: "cust12",
    Orders [{
        OrderId: "ade32f",
        OrderLines: [{
            ItemCount: 50000, //customer really likes gizmos
            ItemName: "gizmo"
        }]
    }]
}]

但我实际得到的是所有客户(那里没有过滤器)、所有他们的订单(那里没有过滤器)和所有订单项, 大部分是空的(过滤掉里面的项目).

But what I actually get is all customers (no filter there), all their orders (no filter there) and all order items, mostly empty (the items inside are filtered).

[{
    Name: "cust12",
    Orders [
    {
        OrderId: "aaaaaa",
        OrderLines: [ ]
    },
    {
        OrderId: "ade32f",
        OrderLines: [{
            ItemCount: 50000,
            ItemName: "gizmo"
        }]
    },
    {
        OrderId: "bbbbbb",
        OrderLines: [ ]
    },
    {
        OrderId: "cccccc",
        OrderLines: [ ]
    }
    ]
},
{
    Name: "cust345",
    Orders [
    {
        OrderId: "eeeeee",
        OrderLines: [ ]
    },
    {
        OrderId: "ffffff",
        OrderLines: [ ]
    }
    ]
}]

GraphQL 调用解析器自顶向下:- 获取所有(过滤的)客户- 对于每一个获取所有(过滤的)订单- 对于每个获取所有(过滤的)订单行

GraphQL calls the resolvers top-down:- get all (filtered) clients- for each of these get all (filtered) orders- for each of those get all (filtered) order lines

由于调用解析器的自上而下性质,我得到的数据比我预想的要多得多.

Because of the top-down nature of calling the resolvers, I get a lot more data than I bargained for.

我应该如何处理这个问题?

How should I approach this?

推荐答案

关系过滤器

这实际上是一个比乍看起来更复杂的话题.问题是您当前的过滤条件表示

Relation filters

This is actually a more complex topic than it first seems. The problem is that your current filter condition expresses

获取所有客户,但只包含名为gizmo"的项目

但你真正想要的是

获取与至少一个名为gizmo"的项目相关的所有客户

获取与至少一个名为gizmo"的项目相关的所有客户

这个问题的一个优雅的解决方案是在模式中添加关系过滤器.在您的情况下,它可能如下所示:

get all customers that are related to at least one item named 'gizmo'

An elegant solution for this problem is the addition of relation filters to the schema. In your case, it could look like this:

query {
  Customer(filter: {
    orders_some: {
      orderLines_some: {
        item: {
          itemName: "gizmo"
        }
      }
    }
  }) {
    Name
    Orders {
      OrderId
      Date
      OrderLines { 
        ItemCount
        ItemName
      }
    }
  }
}

使用

orders_some: {
  orderLines_some: {
    item: {
      itemName: "gizmo"
    }
  }
}

我们只获取与名为gizmo"的项目间接相关的客户,这正是我们想要的.

we only fetch customers that are indirectly related to an item named 'gizmo', exactly what we wanted.

另外两个例子:

query {
  Customer(filter: {
    orders_none: {
      orderLines_some: {
        item: {
          itemName: "gizmo"
        }
      }
    }
  }) {
    Name
    Orders {
      OrderId
      Date
      OrderLines { 
        ItemCount
        ItemName
      }
    }
  }
}

获取所有客户,他们的所有订单都包含一些订单行,其中包含一个名为gizmo"的项目

query {
  Customer(filter: {
    orders_every: {
      orderLines_some: {
        item: {
          itemName: "gizmo"
        }
      }
    }
  }) {
    Name
    Orders {
      OrderId
      Date
      OrderLines { 
        ItemCount
        ItemName
      }
    }
  }
}

everysomenone 关系过滤器是 Graphcool API 的重要组成部分 - 您可以在这里阅读更多内容.

The every, some and none relation filters are an essential part of the Graphcool APIs - you can read more here.

这篇关于GraphQL - 如何过滤层次结构?(“上个月订购了小玩意儿的客户")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!