javascript - 将 Apollo GraphQL 查询解析为包含和属性字段的 Sequelize 查询

标签 javascript recursion graphql sequelize.js apollo

我正在与 Apollo 合作,为我的 GraphQL 请求构建解析器。

为了提高效率,我想获取请求的模型列表(具有相应的嵌套)以及每个模型请求的字段。这样我可以将此信息传递给 sequelize仅在需要时加入模型 - 并且仅提取必要的字段。

解析器会在 info 中传递此信息。目的。

(obj, args, { models }, info) => ...

来自 info对象字段、嵌套模型及其各自的选定字段通过此路径公开:
info.fieldNodes[0].selectionSet.selections

我的问题是将这个结构(以我想象的某种递归方式)解析成一个合理的结构,以便我传递给 sequelize查询。

一个示例 GraphQL 查询:
{
  getCompany(id: 1) {
    id
    name
    companyOffices {
      id
      users {
        id
        title
        userLinks {
          id
          linkUrl
        }
      }
    }
  }
}

info.fieldNodes[0].selectionSet.selections 上生成以下内容(为简洁起见, trim 一些字段):
[
   {
      "kind":"Field",
      "name":{
         "kind":"Name",
         "value":"id"
      }
   },
   {
      "kind":"Field",
      "name":{
         "kind":"Name",
         "value":"name"
      }
   },
   {
      "kind":"Field",
      "name":{
         "kind":"Name",
         "value":"companyOffices"
      },
      "selectionSet":{
         "kind":"SelectionSet",
         "selections":[
            {
               "kind":"Field",
               "name":{
                  "kind":"Name",
                  "value":"id"
               }
            },
            {
               "kind":"Field",
               "name":{
                  "kind":"Name",
                  "value":"users"
               },
               "selectionSet":{
                  "kind":"SelectionSet",
                  "selections":[
                     {
                        "kind":"Field",
                        "name":{
                           "kind":"Name",
                           "value":"id"
                        }
                     },
                     {
                        "kind":"Field",
                        "name":{
                           "kind":"Name",
                           "value":"title"
                        }
                     },
                     {
                        "kind":"Field",
                        "name":{
                           "kind":"Name",
                           "value":"userLinks"
                        },
                        "selectionSet":{
                           "kind":"SelectionSet",
                           "selections":[
                              {
                                 "kind":"Field",
                                 "name":{
                                    "kind":"Name",
                                    "value":"id"
                                 }
                              },
                              {
                                 "kind":"Field",
                                 "name":{
                                    "kind":"Name",
                                    "value":"linkUrl"
                                 }
                              }
                           ]
                        }
                     }
                  ]
               }
            }
         ]
      }
   }
]

使用此信息,我想生成如下查询:
  const company = await models.Company.findOne({
    where: { id: args.id },
    attributes: // DYNAMIC BASED ON QUERY
    include: // DYNAMIC BASED ON QUERY
  });

所以我需要从上面的 info 中将上面的 GraphQL 查询解析为类似这样的结构目的:
{
  attributes: ["id", "name"],
  include: [
    {
      model: "companyOffices",
      attributes: ["id"],
      include: [
        {
          model: users,
          attributes: ["id", "title"],
          include: [{ model: "userLinks", attributes: ["id", "linkUrl"] }]
        }
      ]
    }
  ]
};

但我不清楚如何通过递归来实现这一点,而不会让事情变得困惑。如果有更简单的方法来实现这种动态include/attributes我也对此持开放态度。

tl;dr - 我如何将 Apollo GraphQL 查询的模型和字段转移到 includeattributessequelize询问?

最佳答案

它可能会绕过这个问题,但我想知道是否像 graphql-sequelize可以帮助解决这样的事情。如果没有,我用过 this strategy完成您问题的属性部分。

const mapAttributes = (model, { fieldNodes }) => {
  // get the fields of the Model (columns of the table)
  const columns = new Set(Object.keys(model.rawAttributes));
  const requested_attributes = fieldNodes[0].selectionSet.selections
    .map(({ name: { value } }) => value);
  // filter the attributes against the columns
  return requested_attributes.filter(attribute => columns.has(attribute));
};
User: async (
    _, // instance (not used in Type resolver)
    { username, ... }, // arguments 
    { models: { User }, ... }, // context
    info,
  ) => {
    if (username) {  
      // (only requested columns queried)
      return User.findOne({
        where: { username },
        attributes: mapAttributes(User, info),
      });
    } ... 
  }

关于javascript - 将 Apollo GraphQL 查询解析为包含和属性字段的 Sequelize 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56147436/

相关文章:

c - 递归调用 pipeline() 后 I/O 挂起

javascript - PHP codeigniter动态获取数据时如何隐藏td?

javascript - 为 CDN 实现正确的 CSP 规则

r - 修改列表的非递归版本?

reactjs - 如何使用 graphQL 在 React/Apollo 中 setState()

javascript - 类型-GraphQL : Allow document owner and admin/moderator access with the @Authorized() decorator

java - 如何从 Java 应用程序调用 GraphQL 端点

javascript - 为什么我的脚本不会在每次页面加载时运行?

javascript - 使用右折和差异列表对列表进行教堂编码

c# - 避免递归