Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,22 @@ const example = query({
ctx,
{ latitude: 40.7813, longitude: -73.9737 },
maxResults,
maxDistance,
{
maxDistance,
filter: (q) => q.eq("category", "coffee"),
},
);
return result;
},
});
```

The `maxDistance` parameter is optional, but providing it can greatly speed up
searching the index.
The fourth argument can either be a numeric `maxDistance` (for backwards
compatibility) or an options object. When you pass an options object you can
combine `maxDistance` with the same filter builder used by `query`, including
`eq`, `in`, `gte`, and `lt` conditions. Filtering helps constrain the search
space and can speed up lookups. The `maxDistance` parameter is optional, but
providing it can greatly speed up searching the index.

## Example

Expand Down
23 changes: 2 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,4 @@
},
"types": "./dist/client/index.d.ts",
"module": "./dist/client/index.js"
}
}
40 changes: 37 additions & 3 deletions src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ export type GeospatialDocument<
sortKey: number;
};

export type QueryNearestOptions<
Doc extends GeospatialDocument = GeospatialDocument,
> = {
maxDistance?: number;
filter?: NonNullable<GeospatialQuery<Doc>["filter"]>;
};

export interface GeospatialIndexOptions {
/**
* The minimum S2 cell level to use when querying. Defaults to 4.
Expand Down Expand Up @@ -209,23 +216,50 @@ export class GeospatialIndex<
* @param ctx - The Convex query context.
* @param point - The point to query for.
* @param maxResults - The maximum number of results to return.
* @param maxDistance - The maximum distance to return results within in meters.
* @param maxDistanceOrOptions - Either the maximum distance in meters or an options object containing filtering logic.
* @param maybeOptions - Additional options when the maximum distance is provided separately.
* @returns - An array of objects with the key-coordinate pairs and their distance from the query point in meters.
*/
async queryNearest(
ctx: QueryCtx,
point: Point,
maxResults: number,
maxDistance?: number,
maxDistanceOrOptions?:
| number
| QueryNearestOptions<GeospatialDocument<Key, Filters>>,
maybeOptions?: QueryNearestOptions<GeospatialDocument<Key, Filters>>,
) {
let options:
| QueryNearestOptions<GeospatialDocument<Key, Filters>>
| undefined;
let maxDistance: number | undefined;
if (
typeof maxDistanceOrOptions === "object" &&
maxDistanceOrOptions !== null
) {
options = maxDistanceOrOptions;
} else {
maxDistance = maxDistanceOrOptions;
options = maybeOptions;
}

const filterBuilder = new FilterBuilderImpl<
GeospatialDocument<Key, Filters>
>();
if (options?.filter) {
options.filter(filterBuilder);
}

const resp = await ctx.runQuery(this.component.query.nearestPoints, {
point,
maxDistance,
maxDistance: options?.maxDistance ?? maxDistance,
maxResults,
minLevel: this.minLevel,
maxLevel: this.maxLevel,
levelMod: this.levelMod,
logLevel: this.logLevel,
filtering: filterBuilder.filterConditions,
sorting: { interval: filterBuilder.interval ?? {} },
});
return resp as { key: Key; coordinates: Point; distance: number }[];
}
Expand Down
Loading