Skip to content

Conversation

@Strift
Copy link
Collaborator

@Strift Strift commented Oct 13, 2025

Pull Request

Related issue

Fixes #1412 and #1415

What does this PR do?

  • extract insidePolygon from instantSearch params
  • add tests that params are formatted properly for sending to Meilisearch
  • add tests to clarify how _geo and _geojson interact
  • update documentation

PR checklist

Please check if your PR fulfills the following requirements:

  • Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
  • Have you read the contributing guidelines?
  • Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!

Summary by CodeRabbit

  • New Features

    • Polygon-based geo filtering (insidePolygon) that takes precedence over bounding-box and radius rules.
    • Optional GeoJSON Point support for geo-enabled records.
  • Bug Fixes / Stability

    • Invalid or malformed polygons are ignored to prevent errors.
    • Test cleanup to avoid leftover test data.
  • Tests

    • Added geo-focused tests covering polygons, bounding boxes, and radius behaviors.
  • Documentation

    • README and examples updated with insidePolygon usage and GeoJSON requirements.
  • Playgrounds

    • Demo migrated to modern Maps loader, removed legacy CSS class on search box, added env example, ignored .env, refreshed widgets and dependencies.

@Strift Strift self-assigned this Oct 13, 2025
@Strift Strift added the enhancement New feature or request label Oct 13, 2025
@changeset-bot
Copy link

changeset-bot bot commented Oct 13, 2025

🦋 Changeset detected

Latest commit: a305a0d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@meilisearch/instant-meilisearch Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Oct 13, 2025

Walkthrough

Adds insidePolygon support across the adapter, tests, docs, and playgrounds: adapters accept and validate polygon coordinates (≥3 points), produce a _geoPolygon filter that takes precedence over other geo params, thread insidePolygon through adapters and tests, update test City type to optionally include _geojson, and update playground/README and deps.

Changes

Cohort / File(s) Summary
Geo rules adapter implementation
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts
Add insidePolygon param to adaptGeoSearch; validate ≥3 [lat, lng] pairs (filter out NaN), format points into [lat, lng] strings, and return a _geoPolygon filter immediately (takes precedence over other geo filters).
Search params integration
packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts
addGeoSearchFilter now extracts insidePolygon from searchContext and forwards it to adaptGeoSearch.
Adapter unit tests for geo rules
packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts
New tests: polygon formatting (triangle, quadrilateral), precedence of insidePolygon over insideBoundingBox/around*, and ignoring invalid polygons (<3 points).
Integration geosearch tests
packages/instant-meilisearch/__tests__/geosearch.test.ts
Index setup updated to include _geojson in filterableAttributes; added tests for insidePolygon inclusion/exclusion, behavior with docs missing _geojson, aroundRadius matching _geojson-only docs, and cleanup of created test docs.
Test assets/types
packages/instant-meilisearch/__tests__/assets/utils.ts
Extend exported City type with optional _geojson?: { type: 'Point'; coordinates: [number, number] }.
Documentation
packages/instant-meilisearch/README.md
Document insidePolygon parameter, usage example, precedence rules, note to include _geojson in index filterableAttributes, and update geosearch/playground instructions.
Playground HTML
playgrounds/geo-javascript/index.html
Remove AIS CSS class from the search box element (<div id="searchbox" class="ais-SearchBox"><div id="searchbox">).
Playground app changes
playgrounds/geo-javascript/src/app.js
Replace script-injected Google Maps with @googlemaps/js-api-loader, read API key from import.meta.env, update index to world_cities_geojson, change host to edge.meilisearch.com, and rework widget/init flow and templates.
Playground env & deps
playgrounds/geo-javascript/.env, playgrounds/geo-javascript/.env.example, playgrounds/geo-javascript/package.json, playgrounds/geo-javascript/.gitignore
Remove committed .env, add .env.example with VITE_GOOGLE_MAPS_API_KEY, swap scriptjs for @googlemaps/js-api-loader, update @meilisearch/instant-meilisearch spec, and add .env to .gitignore.
Changeset
.changeset/mean-weeks-admire.md
New changeset noting feature: "Add support for insidePolygon filter to geosearch".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as InstantSearch Widget
  participant SPA as search-params-adapter
  participant GRA as geo-rules-adapter
  participant MS as Meilisearch

  UI->>SPA: build search params (insidePolygon, insideBoundingBox, around*)
  SPA->>GRA: adaptGeoSearch({ insidePolygon, ... })
  alt insidePolygon valid (>=3 points)
    note right of GRA #DFF2E1: Validate points, drop NaN\nFormat into string pairs\nRequire docs to have `_geojson`
    GRA-->>SPA: return `_geoPolygon` filter
  else invalid or absent polygon
    note right of GRA #FFF4E5: Fallback to aroundLatLng/aroundRadius\nor insideBoundingBox (existing logic)
    GRA-->>SPA: return other geo filter or undefined
  end
  SPA->>MS: search(query, filters including _geoPolygon if present)
  MS-->>SPA: hits
  SPA-->>UI: results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review focus:
    • geo-rules-adapter.ts: coordinate validation, NaN handling, formatting, and strict precedence behavior.
    • Integration tests: ensure index setup, _geojson filterableAttributes, and cleanup are correct and stable.
    • Playground changes: API loader usage, env var handling, and dependency updates.
    • Docs: ensure examples and wording accurately describe runtime requirements (documents must have _geojson for polygon search).

Poem

I drew a carrot-shaped polygon tonight,
Three points or more and the filter's just right.
Brussels hops in, Paris stays out —
GeoJSON crumbs with a joyful shout.
—🐰🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Add _insidePolygon support to geosearch" clearly references the main objective of the changeset. The title accurately reflects the primary feature being implemented across multiple files: introducing insidePolygon parameter handling in the geo-rules adapter, adding comprehensive tests, updating documentation, and implementing playground examples. The leading underscore in the title appears to reference the Meilisearch _geoPolygon filter format rather than the instantsearch parameter name, which is a minor naming inconsistency but does not obscure the intent or clarity of the primary change being made.
Linked Issues Check ✅ Passed All primary coding requirements from issue #1412 have been successfully addressed. The geo-rules-adapter.ts file has been updated to recognize and handle the insidePolygon parameter, converting it into a _geoPolygon filter with appropriate precedence logic and validation. Comprehensive tests have been added covering insidePolygon with various polygon shapes, precedence over other geo filters, and edge cases with invalid polygons. Documentation has been updated in README.md with usage descriptions and code samples demonstrating the new parameter configuration. The implementation includes proper validation ensuring at least three coordinate pairs are required for valid polygons.
Out of Scope Changes Check ✅ Passed The changes are appropriately scoped to implementing insidePolygon support for geosearch. Core changes directly implement the feature: updating geo-rules-adapter.ts with the new parameter, adding the _geojson field to the City test type to reflect the new data structure, and updating tests. Playground updates are supportive of the feature implementation, including migrating to @googlemaps/js-api-loader and updating the data source from world_cities to world_cities_geojson to work with the new _geojson field. These changes appear aligned with demonstrating and validating the new functionality rather than introducing unrelated improvements.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/add-geopolygon-filter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)

19-22: Consider adding precision control for consistency.

Unlike the existing aroundLatLng handling (line 35) which uses .toFixed(5) to control floating-point precision, the polygon coordinates don't limit decimal places. While not critical, this inconsistency could lead to unexpected filter strings with high-precision input.

Apply this diff for consistency:

-        const lat = Number.parseFloat(String(pair[0]))
-        const lng = Number.parseFloat(String(pair[1]))
+        const lat = Number.parseFloat(String(pair[0])).toFixed(5)
+        const lng = Number.parseFloat(String(pair[1])).toFixed(5)
         if (Number.isNaN(lat) || Number.isNaN(lng)) return null
-        return `[${lat}, ${lng}]`
+        return `[${Number(lat)}, ${Number(lng)}]`

Note: This mirrors the precision handling used for aroundLatLng at line 35.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 043669a and ec89b9f.

📒 Files selected for processing (5)
  • packages/instant-meilisearch/__tests__/assets/utils.ts (1 hunks)
  • packages/instant-meilisearch/__tests__/geosearch.test.ts (2 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (2 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/instant-meilisearch/__tests__/geosearch.test.ts (1)
packages/instant-meilisearch/__tests__/assets/utils.ts (1)
  • City (225-230)
packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)
  • adaptGeoSearch (3-65)
packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)
  • adaptGeoSearch (3-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: autocomplete-client end-to-end-tests
  • GitHub Check: instant-meilisearch end-to-end-tests
🔇 Additional comments (8)
packages/instant-meilisearch/__tests__/assets/utils.ts (1)

107-222: LGTM! GeoJSON support correctly added to test data.

The implementation correctly adds _geojson fields alongside existing _geo fields, properly following the GeoJSON Point format with coordinates in [longitude, latitude] order. The optional type annotation is appropriate since not all documents may have GeoJSON data.

Also applies to: 229-229

packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)

14-30: Polygon precedence correctly implemented.

The logic properly prioritizes insidePolygon over other geo filters and includes robust validation:

  • Filters invalid coordinate pairs
  • Ensures at least 3 valid points for a valid polygon
  • Short-circuits to avoid unnecessary processing
packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1)

207-222: LGTM! Parameter correctly threaded through.

The insidePolygon parameter is properly destructured from the search context and passed to adaptGeoSearch, maintaining consistency with how other geo parameters are handled.

packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1)

85-136: Excellent test coverage for polygon functionality.

The test suite comprehensively validates:

  • Polygon conversion for different shapes (triangle, quadrilateral)
  • Precedence behavior ensuring insidePolygon takes priority over insideBoundingBox and radius-based filters
  • Graceful handling of invalid input with fewer than 3 points

The expected filter format _geoPolygon([lat, lng], ...) correctly matches Meilisearch's syntax.

packages/instant-meilisearch/__tests__/geosearch.test.ts (4)

14-14: Filterable attributes correctly expanded for polygon support.

Adding '_geojson' to the filterable attributes alongside '_geo' enables polygon-based geo search. This aligns with Meilisearch v1.22.0's polygon support requirements.


112-133: LGTM! Polygon search test validates expected behavior.

The test correctly verifies that documents within the defined polygon (Brussels) are included while documents outside (Paris) are excluded, demonstrating that the insidePolygon parameter is properly translated into a working _geoPolygon filter.


135-168: Good coverage of _geojson field requirement.

This test correctly validates an important constraint: the _geoPolygon filter in Meilisearch only matches documents with the _geojson field. Documents with only _geo are properly excluded from polygon searches. The test includes appropriate cleanup of the test document.


170-202: Validates interoperability between _geo and _geojson fields.

This test confirms that radius-based geo searches (using _geoRadius) work with documents that have only _geojson fields, demonstrating good backward compatibility in Meilisearch's geo search implementation. The test includes proper cleanup.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)

14-30: Consider: Coordinate precision consistency.

For consistency with aroundLatLng processing (line 35, which uses .toFixed(5)), consider whether polygon coordinates should also be formatted to 5 decimal places. However, this may not be necessary if Meilisearch handles precision internally.

If desired for consistency:

 const formattedPoints = insidePolygon
   .map((pair) => {
     if (!Array.isArray(pair) || pair.length < 2) return null
     const lat = Number.parseFloat(String(pair[0]))
     const lng = Number.parseFloat(String(pair[1]))
     if (Number.isNaN(lat) || Number.isNaN(lng)) return null
-    return `[${lat}, ${lng}]`
+    return `[${lat.toFixed(5)}, ${lng.toFixed(5)}]`
   })
   .filter((pt): pt is string => pt !== null)
packages/instant-meilisearch/__tests__/geosearch.test.ts (1)

135-171: Document _geojson requirement for polygon geosearch
Polygon filters (insidePolygon / _geoPolygon) only work with GeoJSON shapes (_geojson). Update the geosearch docs (README or API reference) to note that documents must include a valid _geojson field to be returned in polygon searches (you can retain _geo for distance-based sorting).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 043669a and 1e84be5.

📒 Files selected for processing (5)
  • packages/instant-meilisearch/__tests__/assets/utils.ts (1 hunks)
  • packages/instant-meilisearch/__tests__/geosearch.test.ts (2 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (2 hunks)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)
  • adaptGeoSearch (3-65)
packages/instant-meilisearch/__tests__/geosearch.test.ts (1)
packages/instant-meilisearch/__tests__/assets/utils.ts (1)
  • City (285-290)
packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1)
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)
  • adaptGeoSearch (3-65)
🔇 Additional comments (8)
packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts (1)

207-231: LGTM! Clean parameter threading.

The addition of insidePolygon to the destructuring and its pass-through to adaptGeoSearch correctly wires the new polygon geo-search capability. The change is minimal and aligns with the updated function signature.

packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/geo-rules.test.ts (1)

85-136: LGTM! Comprehensive test coverage for polygon geo-search.

The new test suite thoroughly validates insidePolygon behavior:

  • Basic functionality with triangle and quadrilateral polygons
  • Precedence over insideBoundingBox and around* parameters
  • Graceful handling of invalid input (< 3 points)

The tests align well with the implementation and cover both happy paths and edge cases.

packages/instant-meilisearch/__tests__/assets/utils.ts (2)

285-290: LGTM! Correct GeoJSON Point structure.

The addition of the optional _geojson field correctly models a GeoJSON Point with coordinates in [lng, lat] order, which is the GeoJSON standard. The optional nature maintains backward compatibility with existing tests.


107-282: Coordinate consistency confirmed. All entries in geoDataset have matching _geo and _geojson coordinates.

packages/instant-meilisearch/__tests__/geosearch.test.ts (3)

14-14: LGTM! Necessary filterable attribute addition.

Adding '_geojson' to the filterable attributes is required for polygon-based geo queries to function properly in Meilisearch.


112-133: LGTM! Well-structured polygon geo-search test.

The test correctly validates insidePolygon functionality by:

  • Using a triangle polygon around the Brussels area
  • Confirming Brussels is included in results
  • Confirming Paris (far outside) is excluded

The polygon coordinates follow the [lat, lng] convention used by InstantSearch.


173-205: LGTM! Good test coverage for _geojson compatibility.

This test confirms that radius-based geo queries work with _geojson-only documents, demonstrating interoperability between the two geo field formats. Proper cleanup is included.

packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (1)

14-30: LGTM! Robust polygon validation and precedence logic.

The implementation correctly:

  • Validates polygon structure (array with ≥3 coordinate pairs)
  • Parses and validates each coordinate pair, filtering invalid entries
  • Ensures at least 3 valid points remain after validation
  • Returns immediately to establish precedence over other geo filters
  • Formats output consistent with existing _geoRadius and _geoBoundingBox filters

The validation is thorough with appropriate NaN checks and defensive array length checks.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/instant-meilisearch/README.md (2)

794-794: Enhance documentation with reference link and clarify settings configuration.

The insidePolygon documentation is clear, but could be improved:

  1. Add a link to Meilisearch's documentation on _geojson for users who need to understand how to configure their index
  2. Consider adding a brief note that the filterableAttributes setting must be configured via the Meilisearch API or dashboard (before using this parameter)

Apply this diff to add the documentation link:

-- `insidePolygon`: Filters search results to only include documents whose coordinates fall within a specified polygon. This parameter accepts an array of coordinate pairs `[[lat, lng], [lat, lng], ...]` that define the polygon vertices (minimum 3 points required). When `insidePolygon` is specified, it takes precedence over `insideBoundingBox` and `around*` parameters. **Note**: This feature requires `_geojson` to be added to your Meilisearch index's `filterableAttributes` setting.
+- `insidePolygon`: Filters search results to only include documents whose coordinates fall within a specified polygon. This parameter accepts an array of coordinate pairs `[[lat, lng], [lat, lng], ...]` that define the polygon vertices (minimum 3 points required). When `insidePolygon` is specified, it takes precedence over `insideBoundingBox` and `around*` parameters. **Note**: This feature requires `_geojson` to be added to your Meilisearch index's [`filterableAttributes` setting](https://www.meilisearch.com/docs/reference/api/settings#filterable-attributes) (configured via the Meilisearch API or dashboard before performing searches).

821-839: Clear and well-structured example.

The usage example effectively demonstrates the insidePolygon feature with:

  • Clear comments about the prerequisite settings
  • Proper coordinate array format
  • Valid polygon (3 vertices forming a triangle)

One minor improvement: Consider clarifying that the filterableAttributes setting must be configured using the Meilisearch settings API or dashboard before using this parameter, as it cannot be set directly in the InstantSearch configuration.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e84be5 and 8672d57.

📒 Files selected for processing (1)
  • packages/instant-meilisearch/README.md (2 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/instant-meilisearch/README.md (1)

794-794: Improve readability by breaking up the long paragraph.

The documentation for insidePolygon is comprehensive but presented as a single 300+ character line, which impacts readability. Consider breaking it into a bulleted list.

Apply this diff to improve readability:

-- `insidePolygon`: Filters search results to only include documents whose coordinates fall within a specified polygon. This parameter accepts an array of coordinate pairs `[[lat, lng], [lat, lng], ...]` that define the polygon vertices (minimum 3 points required). When `insidePolygon` is specified, it takes precedence over `insideBoundingBox` and `around*` parameters. Polygon filters require documents to contain a valid `_geojson` field with [GeoJSON format](https://geojson.org/). Documents without `_geojson` will not be returned in polygon searches, even if they have `_geo` coordinates.
+- `insidePolygon`: Filters search results to only include documents whose coordinates fall within a specified polygon.
+  - Accepts an array of coordinate pairs: `[[lat, lng], [lat, lng], ...]` (minimum 3 points required)
+  - Takes precedence over `insideBoundingBox` and `around*` parameters when specified
+  - Requires documents to contain a valid `_geojson` field with [GeoJSON format](https://geojson.org/)
+  - Documents without `_geojson` will not be returned in polygon searches, even if they have `_geo` coordinates
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8672d57 and ba24fb2.

📒 Files selected for processing (3)
  • packages/instant-meilisearch/README.md (2 hunks)
  • playgrounds/geo-javascript/index.html (1 hunks)
  • playgrounds/geo-javascript/src/app.js (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • playgrounds/geo-javascript/index.html
🧰 Additional context used
🧬 Code graph analysis (1)
playgrounds/geo-javascript/src/app.js (4)
playgrounds/javascript/src/app.js (1)
  • search (4-13)
packages/instant-meilisearch/src/client/instant-meilisearch-client.ts (1)
  • instantMeiliSearch (46-212)
playgrounds/node-env/index.js (1)
  • instantMeiliSearch (4-8)
playgrounds/react/src/App.jsx (1)
  • instantMeiliSearch (18-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: instant-meilisearch end-to-end-tests
🔇 Additional comments (4)
playgrounds/geo-javascript/src/app.js (3)

5-5: LGTM: Correct environment variable access for modern bundlers.

The change from process.env.GOOGLE_API to import.meta.env.GOOGLE_API is appropriate for Vite or other modern bundlers that use import.meta.env for environment variables.


11-11: LGTM: Index name updated consistently.

The index name change from world_cities to world_cities_geojson aligns with the PR's addition of polygon support and is consistently applied across all references.

Also applies to: 23-31


13-13: Verify Meilisearch host and index accessibility. A direct check against https://edge.meilisearch.com/indexes/world_cities_geojson with the existing API key returned 401. Ensure that edge.meilisearch.com is the correct host, the API key has access, and the world_cities_geojson index exists there.

packages/instant-meilisearch/README.md (1)

820-834: LGTM: Clear and helpful polygon filtering example.

The code example demonstrates insidePolygon usage effectively, following the existing documentation patterns. The coordinates form a valid triangle around Brussels (matching the test data), and the reference to the geosearch documentation provides users with additional context.

@Strift Strift marked this pull request as draft October 21, 2025 07:39
@curquiza
Copy link
Member

@dureuill I know JS is not your main language, but it's more a review for the geosearch part, if relevant, to help Bruno who has less context on Geosearch. Tell me if not at all.

@Strift
Copy link
Collaborator Author

Strift commented Oct 21, 2025

The feature is ready but I need to do #1415 to update the geosearch playground

@Strift Strift marked this pull request as ready for review October 27, 2025 12:15
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
playgrounds/geo-javascript/package.json (1)

7-9: vite is used in scripts but not declared.

Add vite as a devDependency to avoid env‑specific failures.

Example:

   "scripts": {
     "dev": "vite"
   },
+  "devDependencies": {
+    "vite": "^5"
+  },

Confirm the project’s Node/Vite constraints before pinning a specific minor.

playgrounds/geo-javascript/src/app.js (3)

3-13: Verify js-api-loader API usage; consider Loader pattern.

Confirm that setOptions/importLibrary are valid named exports for @googlemaps/js-api-loader ^2.0.1 in your toolchain. If not, switch to the widely used Loader API.

Alternative:

import { Loader } from '@googlemaps/js-api-loader'

const loader = new Loader({ apiKey: GOOGLE_MAP_API_KEY, version: 'weekly' })
loader.importLibrary('maps').then(() => {
  // init InstantSearch here
})

Optionally, I can check the package docs for the exact API for your version.


40-42: Showcase the new insidePolygon feature in the playground.

Add insidePolygon to configure so users can see polygon filtering in action.

Apply this diff:

     instantsearch.widgets.configure({
-      hitsPerPage: 20,
+      hitsPerPage: 20,
+      // Demo: filter results within a polygon
+      insidePolygon: [
+        [50.8466, 4.35],
+        [50.75, 4.1],
+        [50.65, 4.5],
+      ],
     }),

(If this is deferred to #1415, feel free to skip here.)


55-71: Avoid highlighting numeric fields.

helpers.highlight on population (numeric) is unnecessary; render raw value.

Apply this diff:

-            <div class="hit-name">
-              Population: {{#helpers.highlight}}{ "attribute": "population" }{{/helpers.highlight}}
-            </div>
+            <div class="hit-name">
+              Population: {{population}}
+            </div>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba24fb2 and 922b3b1.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • playgrounds/geo-javascript/.env (1 hunks)
  • playgrounds/geo-javascript/index.html (2 hunks)
  • playgrounds/geo-javascript/package.json (1 hunks)
  • playgrounds/geo-javascript/src/app.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
playgrounds/geo-javascript/src/app.js (2)
playgrounds/javascript/src/app.js (1)
  • search (4-13)
packages/instant-meilisearch/src/client/instant-meilisearch-client.ts (1)
  • instantMeiliSearch (46-212)
🪛 Gitleaks (8.28.0)
playgrounds/geo-javascript/.env

[high] 1-1: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.

(gcp-api-key)

🔇 Additional comments (2)
playgrounds/geo-javascript/index.html (1)

35-35: Search box container class change — verify styling.

Dropping the ais-SearchBox class from the container is usually fine (the widget injects its own classes). Just confirm no custom CSS relied on the container having that class.

playgrounds/geo-javascript/src/app.js (1)

14-20: Public demo key check for Meilisearch.

Confirm the API key used here is a public demo key with strict origin/route limits. If not, move it to env and restrict it.

Copy link

@dureuill dureuill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few comments on error handling an API keys. Otherwise I think we're good

@@ -1 +0,0 @@
GOOGLE_API=AIzaSyDOaUaar4GL0i99LpN2zQHzfWXL1wu_JQo

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we revoke this api key?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but it's been public for years now.

And since this API key is intended for use in client-side JavaScript anyway, it's safe to share imo.

That said, @curquiza, if you want to revoke + recreate, you can.

Comment on lines +16 to +17
'https://edge.meilisearch.com',
'a63da4928426f12639e19d62886f621130f3fa9ff3c7534c5d179f0f51c4f303',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have an URL + api key in the code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the current practice for most basic examples in our codebases

if (Array.isArray(insidePolygon) && insidePolygon.length >= 3) {
const formattedPoints = insidePolygon
.map((pair) => {
if (!Array.isArray(pair) || pair.length < 2) return null

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. what happens when we return null? Is that ignoring the error silently?
  2. are we silently ignoring extra coordinates rather than returning an error?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, errors were silently ignored.

I updated the code to log warnings when coordinate pairs are malformed.

I chose this approach because this file already contains warnings for other ignored parameters:

      console.warn(
        'instant-meilisearch is not compatible with the `all` value on the aroundRadius parameter'
      )

@Strift Strift requested a review from dureuill October 30, 2025 11:23
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab4af73 and a305a0d.

📒 Files selected for processing (1)
  • packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts (2 hunks)

Comment on lines +15 to +43
if (Array.isArray(insidePolygon) && insidePolygon.length >= 3) {
const invalidPairs: unknown[] = []

const formattedPoints = insidePolygon
.map((pair) => {
if (!Array.isArray(pair) || pair.length < 2) {
invalidPairs.push(pair)
return null
}
const lat = Number.parseFloat(String(pair[0]))
const lng = Number.parseFloat(String(pair[1]))
if (Number.isNaN(lat) || Number.isNaN(lng)) {
invalidPairs.push(pair)
return null
}
return `[${lat}, ${lng}]`
})
.filter((pt): pt is string => pt !== null)

if (invalidPairs.length > 0) {
console.warn(
'instant-meilisearch: insidePolygon contains invalid coordinate pairs that were ignored:',
invalidPairs
)
}

if (formattedPoints.length >= 3) {
filter = `_geoPolygon(${formattedPoints.join(', ')})`
return filter
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

insidePolygon parsing drops required coordinates

InstantSearch sends insidePolygon as an array of polygons, and each polygon is a flattened list of lat/lng numbers (minimum six values). Here we iterate the top-level array as if each item were a single [lat, lng] pair, so we discard the remaining coordinates and never reach three points—formattedPoints stays < 3 and _geoPolygon(...) is never returned. In practice, any valid insidePolygon input from InstantSearch falls through to the legacy radius/bounding-box logic, so the new feature is effectively broken. Please chunk each polygon array in steps of two, parse every point, and handle the single-polygon shorthand (insidePolygon: number[]) before emitting _geoPolygon.(algolia.com)

-  if (Array.isArray(insidePolygon) && insidePolygon.length >= 3) {
-    const invalidPairs: unknown[] = []
-
-    const formattedPoints = insidePolygon
-      .map((pair) => {
-        if (!Array.isArray(pair) || pair.length < 2) {
-          invalidPairs.push(pair)
-          return null
-        }
-        const lat = Number.parseFloat(String(pair[0]))
-        const lng = Number.parseFloat(String(pair[1]))
-        if (Number.isNaN(lat) || Number.isNaN(lng)) {
-          invalidPairs.push(pair)
-          return null
-        }
-        return `[${lat}, ${lng}]`
-      })
-      .filter((pt): pt is string => pt !== null)
-
-    if (invalidPairs.length > 0) {
-      console.warn(
-        'instant-meilisearch: insidePolygon contains invalid coordinate pairs that were ignored:',
-        invalidPairs
-      )
-    }
-
-    if (formattedPoints.length >= 3) {
-      filter = `_geoPolygon(${formattedPoints.join(', ')})`
-      return filter
-    }
-  }
+  if (Array.isArray(insidePolygon) && insidePolygon.length > 0) {
+    const polygons = (Array.isArray(insidePolygon[0]) && typeof insidePolygon[0] !== 'number'
+      ? insidePolygon
+      : [insidePolygon]) as unknown[]
+    const invalidPolygons: unknown[] = []
+
+    for (const polygon of polygons) {
+      if (!Array.isArray(polygon) || polygon.length < 6 || polygon.length % 2 !== 0) {
+        invalidPolygons.push(polygon)
+        continue
+      }
+
+      const points: string[] = []
+      for (let i = 0; i < polygon.length; i += 2) {
+        const lat = Number.parseFloat(String(polygon[i]))
+        const lng = Number.parseFloat(String(polygon[i + 1]))
+        if (Number.isNaN(lat) || Number.isNaN(lng)) {
+          invalidPolygons.push(polygon)
+          points.length = 0
+          break
+        }
+        points.push(`[${lat}, ${lng}]`)
+      }
+
+      if (points.length >= 3) {
+        filter = `_geoPolygon(${points.join(', ')})`
+        return filter
+      }
+    }
+
+    if (invalidPolygons.length > 0) {
+      console.warn(
+        'instant-meilisearch: insidePolygon contains invalid coordinates that were ignored:',
+        invalidPolygons
+      )
+    }
+  }
🤖 Prompt for AI Agents
packages/instant-meilisearch/src/adapter/search-request-adapter/geo-rules-adapter.ts
lines 15-43: the current code assumes each entry of insidePolygon is a [lat,lng]
pair, but InstantSearch may send insidePolygon as a single flattened number[]
(shorthand) or as an array of polygons where each polygon is a flattened list of
numbers; modify the parser to first detect if insidePolygon is an array of
numbers (single polygon shorthand) and wrap it as a single polygon array, then
for each polygon iterate in steps of two (chunk the flattened list into
[lat,lng] pairs), parse and validate each pair (collect invalid pairs), build
formattedPoints from all valid pairs across the polygon, and only emit
`_geoPolygon(...)` when you have at least three valid points; keep the
invalidPairs logging behavior but ensure you do not treat each top-level element
as a pair.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

instant-meilisearch: add geoSearch widget example to geo-javascript playground instant-meilisearch: add insidePolygon support to geosearch

4 participants