0

一些上下文:

我的表有两列,经度和纬度。我希望能够创建一个查询,该查询可以接收经度、纬度和表示最大公里数距离的数字的输入。

查询将返回按结果距离排序的该距离内的行。

我已经看到自定义条件的选项很少,但这可能很hacky......我想也许有一种方法可以做到这一点并使用生成的构建order byPostGraphile但我是否有办法将变量传递给的顺序。

问题:

什么是最好的PostGraphile

提前致谢!

4

1 回答 1

2

为此,第 1 步是使用 x、y 和半径构建过滤器对象:

const { makePluginByCombiningPlugins, makeAddPgTableConditionPlugin } = require('graphile-utils');

const PositionFilterObjectPlugin = builder => {
  builder.hook('build', build => {
    const nonNullFloat = new build.graphql.GraphQLNonNull(build.graphql.GraphQLFloat);
    const PositionFilter = new build.graphql.GraphQLInputObjectType({
      name: 'PositionFilter',
      fields: {
        x: {
          type: nonNullFloat,
        },
        y: {
          type: nonNullFloat,
        },
        radius: {
          type: nonNullFloat,
        },
      },
    });
    build.addType(PositionFilter);

    return build;
  });
};

/*
   Due to a plugin ordering issue that cannot be addressed in V4, we can't
   just use makeExtendSchemaPlugin to add this type; we have to write it
   out by hand in the build hook.

   input PositionFilter {
     x: Float!
     y: Float!
     radius: Float!
   }
*/

build.graphql是模块的一个实例,参考 GraphQL 实现,您可以在此处此处graphql阅读有关它的更多信息。)

第 2 步是添加一个可以进行排序的条件:

const PositionConditionPlugin = makeAddPgTableConditionPlugin(
  'public',
  'entities',
  'closeTo',
  build => ({
    type: build.getTypeByName('PositionFilter'),
  }),
  (value, { queryBuilder, sql, sqlTableAlias }) => {
    if (value == null) {
      return;
    }

    const { x, y, radius } = value;
    const valX = sql.value(x);
    const valY = sql.value(x);
    const valR = sql.value(radius);

    const distance = sql.fragment`(((${sqlTableAlias}.x - ${valX}) ^ 2 + (${sqlTableAlias}.y - ${valY}) ^ 2) ^ 0.5)`;

    // Order the result set by the proximity of the entity to the given point
    queryBuilder.orderBy(
      distance,
      true, // Ascending
      false,
    );

    // Filter to only entities within the given radius
    return sql.fragment`${distance} < ${valR}`;
  },
);

最后,您可以加载这两个插件,或者如果您愿意,可以制作一个包含两者的插件:

module.exports = makePluginByCombiningPlugins(PositionFilterObjectPlugin, PositionConditionPlugin);

我在文档中添加了一个订购示例:

https://www.graphile.org/postgraphile/make-add-pg-table-condition-plugin/#example-with-ordering

注意:在 graphile-utils 4.9.1 发布之前,您需要通过--prepend-plugins(或prependPlugins为库用户)添加此插件,否则会出现插件排序问题,这意味着添加的makeAddPgTableConditionPlugin订单在默认订单之后。

于 2020-09-15T14:56:28.290 回答