按计算结果的后记顺序(带输入)
Postgraphile order by result of calculation (with input)
一些上下文:
我的 table 有两列,经度和纬度。
我希望能够创建一个查询,该查询可以接收经度、纬度和代表最大公里数的数字的输入。
查询将return该距离内的行按结果距离排序。
我看到自定义条件的选项很少,但这可能很老套...
我想也许有一种方法可以做到这一点并使用 PostGraphile
生成的 order by
中的构建,但我想如果有一种方法可以将变量传递给 order by.
问题:
在 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 and 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
添加的订单在默认订单之后。
一些上下文:
我的 table 有两列,经度和纬度。 我希望能够创建一个查询,该查询可以接收经度、纬度和代表最大公里数的数字的输入。
查询将return该距离内的行按结果距离排序。
我看到自定义条件的选项很少,但这可能很老套...
我想也许有一种方法可以做到这一点并使用 PostGraphile
生成的 order by
中的构建,但我想如果有一种方法可以将变量传递给 order by.
问题:
在 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 and 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
添加的订单在默认订单之后。