From d39de8d145386f381c240d622387a6c9fe32be9f Mon Sep 17 00:00:00 2001 From: Landon Reed Date: Thu, 29 Mar 2018 16:29:05 -0400 Subject: [PATCH] add bounding box query for stops --- .../gtfs/graphql/GraphQLGtfsSchema.java | 5 ++++ .../conveyal/gtfs/graphql/GraphQLUtil.java | 8 ++++++ .../gtfs/graphql/fetchers/JDBCFetcher.java | 25 ++++++++++++++++--- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/conveyal/gtfs/graphql/GraphQLGtfsSchema.java b/src/main/java/com/conveyal/gtfs/graphql/GraphQLGtfsSchema.java index f44cf3394..73def8f54 100644 --- a/src/main/java/com/conveyal/gtfs/graphql/GraphQLGtfsSchema.java +++ b/src/main/java/com/conveyal/gtfs/graphql/GraphQLGtfsSchema.java @@ -18,6 +18,7 @@ import java.sql.Array; import java.sql.SQLException; +import static com.conveyal.gtfs.graphql.GraphQLUtil.floatArg; import static com.conveyal.gtfs.graphql.GraphQLUtil.intArg; import static com.conveyal.gtfs.graphql.GraphQLUtil.intt; import static com.conveyal.gtfs.graphql.GraphQLUtil.multiStringArg; @@ -633,6 +634,10 @@ public class GraphQLGtfsSchema { .argument(stringArg("namespace")) // FIXME maybe these nested namespace arguments are not doing anything. .argument(multiStringArg("stop_id")) .argument(multiStringArg("pattern_id")) + .argument(floatArg("minLat")) + .argument(floatArg("minLon")) + .argument(floatArg("maxLat")) + .argument(floatArg("maxLon")) .argument(intArg(ID_ARG)) .argument(intArg(LIMIT_ARG)) .argument(intArg(OFFSET_ARG)) diff --git a/src/main/java/com/conveyal/gtfs/graphql/GraphQLUtil.java b/src/main/java/com/conveyal/gtfs/graphql/GraphQLUtil.java index 0b8a829a5..d74180a82 100644 --- a/src/main/java/com/conveyal/gtfs/graphql/GraphQLUtil.java +++ b/src/main/java/com/conveyal/gtfs/graphql/GraphQLUtil.java @@ -5,6 +5,7 @@ import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLList; +import static graphql.Scalars.GraphQLFloat; import static graphql.Scalars.GraphQLInt; import static graphql.Scalars.GraphQLString; import static graphql.schema.GraphQLArgument.newArgument; @@ -49,4 +50,11 @@ public static GraphQLArgument intArg (String name) { .build(); } + public static GraphQLArgument floatArg (String name) { + return newArgument() + .name(name) + .type(GraphQLFloat) + .build(); + } + } diff --git a/src/main/java/com/conveyal/gtfs/graphql/fetchers/JDBCFetcher.java b/src/main/java/com/conveyal/gtfs/graphql/fetchers/JDBCFetcher.java index 2bb855766..41203fdf4 100644 --- a/src/main/java/com/conveyal/gtfs/graphql/fetchers/JDBCFetcher.java +++ b/src/main/java/com/conveyal/gtfs/graphql/fetchers/JDBCFetcher.java @@ -18,8 +18,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static com.conveyal.gtfs.graphql.GraphQLUtil.multiStringArg; import static com.conveyal.gtfs.graphql.GraphQLUtil.stringArg; @@ -39,6 +41,8 @@ public class JDBCFetcher implements DataFetcher>> { public static final String ID_ARG = "id"; public static final String LIMIT_ARG = "limit"; public static final String OFFSET_ARG = "offset"; + public static final List boundingBoxArgs = Arrays.asList("minLat", "minLon", "maxLat", "maxLon"); + public static final List paginationArgs = Arrays.asList(LIMIT_ARG, OFFSET_ARG); public final String tableName; public final String parentJoinField; private final String sortField; @@ -172,11 +176,14 @@ public List> getResults (String namespace, List pare // FIXME add sort order? sortBy = String.format(" order by %s", sortField); } - for (String key : arguments.keySet()) { + Set argumentKeys = arguments.keySet(); + for (String key : argumentKeys) { // Limit and Offset arguments are for pagination. projectStops is used to mutate shape points before // returning them. All others become "where X in A, B, C" clauses. - String[] argsToSkip = new String[]{LIMIT_ARG, OFFSET_ARG}; - if (Arrays.asList(argsToSkip).indexOf(key) != -1) continue; + Set argsToSkip = new HashSet<>(); + argsToSkip.addAll(boundingBoxArgs); + argsToSkip.addAll(paginationArgs); + if (argsToSkip.contains(key)) continue; if (ID_ARG.equals(key)) { Integer value = (Integer) arguments.get(key); conditions.add(String.join(" = ", "id", value.toString())); @@ -185,6 +192,18 @@ public List> getResults (String namespace, List pare if (values != null && !values.isEmpty()) conditions.add(makeInClause(key, values)); } } + if (argumentKeys.containsAll(boundingBoxArgs)) { + // Handle bounding box arguments if all are supplied. + for (String bound : boundingBoxArgs) { + Double value = (Double) arguments.get(bound); + // Determine delimiter/equality operator based on min/max + String delimiter = bound.startsWith("max") ? " <= " : " >= "; + // Determine field based on lat/lon + // FIXME: Currently only works with stops. Add pattern query. + String field = bound.endsWith("Lon") ? "stop_lon" : "stop_lat"; + conditions.add(String.join(delimiter, field, value.toString())); + } + } if ( ! conditions.isEmpty()) { sqlBuilder.append(" where "); sqlBuilder.append(String.join(" and ", conditions));