graphql - Apollo GraphQL 服务器 : filter (or sort) by a field that is resolved separately

标签 graphql apollo-server

我可能面临 Apollo GraphQL server 的设计限制我想问一下是否有解决方法。

我的架构包含类型 Thing ,具有字段 flag .我希望能够过滤 things通过 flag 的值,但如果单独解析该字段似乎是不可能的。如果我想排序 things 也会出现同样的问题.这是一个例子:

  type Thing {
    id: String!
    flag Boolean!
  }

  type Query {
    things(onlyWhereFlagIsTrue: Boolean): [Thing!]!
  }

const resolvers = {
  Thing: {
    flag: async ({id}) => {
      const value = await getFlagForThing(id);
      return value;
    }
  },
  Query: {
    async things(obj, {onlyWhereFlagIsTrue = false}) {
      let result = await getThingsWithoutFlags();
      if (onlyWhereFlagIsTrue) {
        // ↓ this does not work, because flag is still undefined
        result = _.filter(result, ['flag', true]);
      }
      return result;
    }
  }
}

有什么过滤方法things在所有异步字段都解决之后?我知道我可以调用getFlagForThing(id)里面 things解析器,但这不是重复我自己吗?解析 flag 背后的逻辑可能比仅调用一个函数要复杂一些。

更新:这是迄今为止我能找到的最好的解决方案。非常丑陋且难以扩展到其他领域:

const resolvers = {
  Thing: {
    flag: async ({id, flag}) => {
      // need to check if flag has already been resolved
      // to avoid calling getThingsWithoutFlags() twice
      if (!_.isUndefined(flag)) {
        return flag;
      }
      const value = await getFlagForThing(id);
      return value;
    }
  },
  Query: {
    async things(obj, {onlyWhereFlagIsTrue = false}) {
      let result = await getThingsWithoutFlags();
      if (onlyWhereFlagIsTrue) {
        // asynchroniously resolving flags when needed
        const promises = _.map(result, ({id}) =>
          getFlagForThing(id)
        );
        const flags = await Promise.all(promises);
        for (let i = 0; i < flags.length; i += 1) {
          result[i].flag = flags[i];
        }
        // ↓ this line works now
        result = _.filter(result, ['flag', true]);
      }
      return result;
    }
  },
};

最佳答案

我认为这里的问题实际上并不是 Apollo 服务器的限制,而更多地与您有一个带有解析器的原始字段这一事实有关。通常,最好仅在该字段将返回单独的类型时才对字段使用解析器:

Thing {
    id: ID!
    flag: Boolean!
    otherThings: OtherThing
}

Query {
    things(onlyWhereFlag: Boolean): [Thing!]!
}

在此示例中,可以为 otherThings 设置单独的解析器。 ,但是如果一个字段是一个原始字段,那么我只会将该字段与 Thing 一起解析。
使用您的原始架构:

const filterByKeyValuePair = ([key, value]) => obj => obj[key] === value;

const resolvers = {
    Query: {
        async things(parent, { onlyWhereFlag }) {
            const things = await Promise.all(
                (await getThings()).map(
                    thing =>
                        new Promise(async resolve =>
                            resolve({
                                ...thing,
                                flag: await getFlagForThing(thing)
                            })
                        )
                )
            );

            if (onlyWhereFlag) {
                return things.filter(filterByKeyValuePair(['flag', true]));
            } else {
                return things;
            }
        }
    }
};

如果 flag不是原始人吗?好吧,如果您想按它进行过滤,那么您将有几个不同的选择。这些选项实际上取决于您获取“标志”数据的方式。如果您可以提供有关您的架构和数据模型的更多详细信息,我将很乐意详细说明。

关于graphql - Apollo GraphQL 服务器 : filter (or sort) by a field that is resolved separately,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46619596/

相关文章:

node.js - 如何部署 Apollo 客户端和 Node Express/Sequelize API?

interface - GraphQL 接口(interface) : [interface] expects "fieldname" but [type] does not provide it

ruby-on-rails - Rails、Graphql、Apollo 客户端的验证 token 无效

graphql - Apollo GraphQL 变异(对象参数)

sequelize.js - GraphQL/Sequelize : SQL alias

graphql - GraphQL 查询中的数据规范化

graphql - 优化 graphql 数据库查询

node.js - NodeJs GraphQL 枚举类型值作为动态

javascript - 具有网关服务器作为服务的 Apollo 联邦

graphql - 如何使用 sequelize-typescript 通过自定义 Apollo GraphQL 解析器查询相关对象?