繁体   English   中英

GraphQL:从对象构建查询参数

[英]GraphQL: build query arguments from object

如果我有一个对象:

{"where":{"publishedAt_lt":"2018-01-01"}}

如何将其转换为适合查询参数的字符串?

articles(where: {publishedAt_lt: "2018-01-01"})

这不能回答您的问题,但是如果遵循最佳实践,通常不会出现您的问题:GraphQL查询应该是静态的-这意味着您不会从变量输入中生成它们。 也许您有一个有效的用例,但我几乎无法想象。 请在评论中让我知道。

当客户端为字段参数输入变量时,您想使用变量:

query getArticles($filter: ArticlesFilter) { # Please insert your input type name
  articles(where: $filter) {
    # ...
  }
}

然后,您可以在查询的变量字段中传递此输入:

let givenObject = {"where":{"publishedAt_lt":"2018-01-01"}}; // said object
fetch('/graphql', {
  method: 'POST',
  body: JSON.stringify({
    query, // put the query string from above
    variables: {
      filter: givenObject,
    },
  }),
});

现在是纯JS,请参考您的客户端库。 我确定他们有一个有关此内容的文档部分。 对于react-apollo,您可以在此处找到文档如何传递变量。

这看起来像一个有趣的库,我建议您检查一下:

https://www.npmjs.com/package/json-to-graphql-query

但是,基本上我们需要做的就是将对象转换为字符串,同时确保键不采用双引号,并且整数也不会转换为字符串,因为这可能不适用于我们使用的graphql模式。

由于JSON.stringify()无法完成此操作,因此我想到了这个小函数来帮助将参数插值到查询中:

/**
 * Queryfy.
 *
 * Prep javascript objects for interpolation within graphql queries.
 *
 * @param {mixed} obj
 * @return template string.
 */
const queryfy = obj => {

  // Make sure we don't alter integers.
  if( typeof obj === 'number' ) {
    return obj;
  }

  // Stringify everything other than objects.
  if( typeof obj !== 'object' || Array.isArray( obj ) ) {
    return JSON.stringify( obj );
  }

  // Iterate through object keys to convert into a string
  // to be interpolated into the query.
  let props = Object.keys( obj ).map( key =>
    `${key}:${queryfy( obj[key] )}`
  ).join( ',' );

  return `{${props}}`;

}

这是我成功使用此代码的部分简化代码:

const dateQuery = {};

if( !! date1 ) {

  dateQuery.after = {
    year: parseInt( date1.format( 'YYYY' ) ),
    month: parseInt( date1.format( 'M' ) ),
    day: date1.format( 'D' ) - 1,
  }

}
if( !! date2 ) {

  dateQuery.before = {
    year: parseInt( date2.format( 'YYYY' ) ),
    month: parseInt( date2.format( 'M' ) ),
    day: date2.format( 'D' ) - 1,
  }

}

const query = await client.query( {
  query: gql `{
    apiResponses( where: {
      dateQuery: ${queryfy( dateQuery )}
    } ) {
      edges {
        node {
          apiResponseId
          title
          date
          json
        }
      }
    }
  }`
} );

话虽这么说,我将要检查提到的库,并可能会继续使用该库。

尝试这个:

const { where } = {"where":{"publishedAt_lt":"2018-01-01"}}
articleList = articles({where}) // assume articles takes an object - equivalent to articles({where: where}) or articles({where: {publishedAt_lt: "2018-01-01"}}

我采用了KMcAloon方法,并使其也支持数组。 这样,您就可以将查询完全作为一个对象,并在最后一步将其包装=>例如

mutation createPackage {
  createPackage(
    data: ${queryfy(data)}
  ) {
    name
    _id
  })
}

 /** * Queryfy. * * Prep javascript objects for interpolation within graphql queries. * * @param {mixed} obj * @return template string. */ const queryfy = obj => { // Make sure we don't alter integers. if (typeof obj === 'number') { return obj; } if (Array.isArray(obj)) { const props = obj.map(value => `${queryfy(value)}`).join(','); return `[${props}]`; } if (typeof obj === 'object') { const props = Object.keys(obj) .map(key => `${key}:${queryfy(obj[key])}`) .join(','); return `{${props}}`; } return JSON.stringify(obj); }; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM