问题描述
某些上下文:
我的表格有两列,经度和纬度。 我希望能够创建一个查询,该查询可以接收经度,纬度和代表最大公里数的数字的输入。
查询将返回在该距离内按结果距离排序的行。
我见过一些自定义条件的选项,但这可能很hacky ...
我以为也许有一种方法可以使用order by
生成的PostGraphile
中的构建,但是我有办法将变量传递给订单。
问题:
在PostGraphile
中最好的做法是什么?
谢谢!
解决方法
为此,步骤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的参考实现,您可以详细了解here和here。)
第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
添加的添加到默认订单之后。