> ## Documentation Index
> Fetch the complete documentation index at: https://www.meilisearch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Geosearch

> Filter and sort search results based on their geographic location.

This guide walks you through indexing documents with geographic coordinates, then filtering and sorting results by location.

## Add `_geo` to your documents

Documents must contain a `_geo` field with `lat` and `lng` values:

<CodeGroup>
  ```json theme={null}
  [
    {
      "id": 1,
      "name": "Nàpiz' Milano",
      "address": "Viale Vittorio Veneto, 30, 20124, Milan, Italy",
      "type": "pizza",
      "rating": 9,
      "_geo": {
        "lat": 45.4777599,
        "lng": 9.1967508
      }
    },
    {
      "id": 2,
      "name": "Bouillon Pigalle",
      "address": "22 Bd de Clichy, 75018 Paris, France",
      "type": "french",
      "rating": 8,
      "_geo": {
        "lat": 48.8826517,
        "lng": 2.3352748
      }
    },
    {
      "id": 3,
      "name": "Artico Gelateria Tradizionale",
      "address": "Via Dogana, 1, 20123 Milan, Italy",
      "type": "ice cream",
      "rating": 10,
      "_geo": {
        "lat": 45.4632046,
        "lng": 9.1719421
      }
    }
  ]
  ```
</CodeGroup>

<Warning>
  Trying to index a dataset with one or more documents containing badly formatted `_geo` values will cause Meilisearch to throw an [`invalid_document_geo_field`](/reference/errors/error_codes#invalid_document_geo_field) error. In this case, the update will fail and no documents will be added or modified.
</Warning>

<Note>
  Meilisearch also supports [GeoJSON](/capabilities/geo_search/how_to/use_geojson_format) for complex geometries like polygons and multi-polygons.
</Note>

## Configure filterable and sortable attributes

To filter results by location, add `_geo` to `filterableAttributes`:

<CodeGroup>
  ```bash cURL theme={null}
  curl \
    -X PUT 'MEILISEARCH_URL/indexes/restaurants/settings/filterable-attributes' \
    -H 'Content-type:application/json' \
    --data-binary '["_geo"]'
  ```

  ```javascript JS theme={null}
  client.index('restaurants')
  .updateFilterableAttributes([
    '_geo'
  ])
  ```

  ```python Python theme={null}
  client.index('restaurants').update_filterable_attributes([
    '_geo'
  ])
  ```

  ```php PHP theme={null}
  $client->index('restaurants')->updateFilterableAttributes([
    '_geo'
  ]);
  ```

  ```java Java theme={null}
  Settings settings = new Settings();
  settings.setFilterableAttributes(new String[] { "_geo" });
  client.index("restaurants").updateSettings(settings);
  ```

  ```ruby Ruby theme={null}
  client.index('restaurants').update_filterable_attributes(['_geo'])
  ```

  ```go Go theme={null}
  filterableAttributes := []interface{}{
    "_geo",
  }
  client.Index("restaurants").UpdateFilterableAttributes(&filterableAttributes)
  ```

  ```csharp C# theme={null}
  List<string> attributes = new() { "_geo" };
  TaskInfo result = await client.Index("movies").UpdateFilterableAttributesAsync(attributes);
  ```

  ```rust Rust theme={null}
  let task: TaskInfo = client
    .index("restaurants")
    .set_filterable_attributes(&["_geo"])
    .await
    .unwrap();
  ```

  ```swift Swift theme={null}
  client.index("restaurants").updateFilterableAttributes(["_geo"]) { (result) in
      switch result {
      case .success(let task):
          print(task)
      case .failure(let error):
          print(error)
      }
  }
  ```

  ```dart Dart theme={null}
  await client.index('restaurants').updateFilterableAttributes(['_geo']);
  ```
</CodeGroup>

To sort results by distance, add `_geo` to `sortableAttributes`:

<CodeGroup>
  ```bash cURL theme={null}
  curl \
    -X PUT 'MEILISEARCH_URL/indexes/restaurants/settings/sortable-attributes' \
    -H 'Content-type:application/json' \
    --data-binary '["_geo"]'
  ```

  ```javascript JS theme={null}
  client.index('restaurants').updateSortableAttributes([
    '_geo'
  ])
  ```

  ```python Python theme={null}
  client.index('restaurants').update_sortable_attributes([
    '_geo'
  ])
  ```

  ```php PHP theme={null}
  $client->index('restaurants')->updateSortableAttributes([
    '_geo'
  ]);
  ```

  ```java Java theme={null}
  client.index("restaurants").updateSortableAttributesSettings(new String[] {"_geo"});
  ```

  ```ruby Ruby theme={null}
  client.index('restaurants').update_sortable_attributes(['_geo'])
  ```

  ```go Go theme={null}
  sortableAttributes := []string{
    "_geo",
  }
  client.Index("restaurants").UpdateSortableAttributes(&sortableAttributes)
  ```

  ```csharp C# theme={null}
  List<string> attributes = new() { "_geo" };
  TaskInfo result = await client.Index("restaurants").UpdateSortableAttributesAsync(attributes);
  ```

  ```rust Rust theme={null}
  let task: TaskInfo = client
    .index("restaurants")
    .set_sortable_attributes(&["_geo"])
    .await
    .unwrap();
  ```

  ```swift Swift theme={null}
  client.index("restaurants").updateSortableAttributes(["_geo"]) { (result) in
    switch result {
    case .success(let task):
      print(task)
    case .failure(let error):
      print(error)
    }
  }
  ```

  ```dart Dart theme={null}
  await client.index('restaurants').updateSortableAttributes(['_geo']);
  ```
</CodeGroup>

Meilisearch will rebuild your index whenever you update these settings. Depending on the size of your dataset, this might take a considerable amount of time.

## Filter results by location

Use the [`filter` search parameter](/reference/api/search/search-with-post#body-filter) with `_geoRadius` to find results within a given distance from a point. The following example searches for restaurants within 2km of central Milan:

<CodeGroup>
  ```bash cURL theme={null}
  curl \
    -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
    -H 'Content-type:application/json' \
    --data-binary '{ "filter": "_geoRadius(45.472735, 9.184019, 2000)" }'
  ```

  ```javascript JS theme={null}
  client.index('restaurants').search('', {
    filter: ['_geoRadius(45.472735, 9.184019, 2000)'],
  })
  ```

  ```python Python theme={null}
  client.index('restaurants').search('', {
    'filter': '_geoRadius(45.472735, 9.184019, 2000)'
  })
  ```

  ```php PHP theme={null}
  $client->index('restaurants')->search('', [
    'filter' => '_geoRadius(45.472735, 9.184019, 2000)'
  ]);
  ```

  ```java Java theme={null}
  SearchRequest searchRequest = SearchRequest.builder().q("").filter(new String[] {"_geoRadius(45.472735, 9.184019, 2000)"}).build();
  client.index("restaurants").search(searchRequest);
  ```

  ```ruby Ruby theme={null}
  client.index('restaurants').search('', { filter: '_geoRadius(45.472735, 9.184019, 2000)' })
  ```

  ```go Go theme={null}
  resp, err := client.Index("restaurants").Search("", &meilisearch.SearchRequest{
    Filter: "_geoRadius(45.472735, 9.184019, 2000)",
  })
  ```

  ```csharp C# theme={null}
  SearchQuery filters = new SearchQuery() { Filter = "_geoRadius(45.472735, 9.184019, 2000)" };
  var restaurants = await client.Index("restaurants").SearchAsync<Restaurant>("", filters);
  ```

  ```rust Rust theme={null}
  let results: SearchResults<Restaurant> = client
    .index("restaurants")
    .search()
    .with_filter("_geoRadius(45.472735, 9.184019, 2000)")
    .execute()
    .await
    .unwrap();
  ```

  ```swift Swift theme={null}
  let searchParameters = SearchParameters(
      filter: "_geoRadius(45.472735, 9.184019, 2000)"
  )
  client.index("restaurants").search(searchParameters) { (result: Result<Searchable<Restaurant>, Swift.Error>) in
      switch result {
      case .success(let searchResult):
          print(searchResult)
      case .failure(let error):
          print(error)
      }
  }
  ```

  ```dart Dart theme={null}
  await client.index('restaurants').search(
        '',
        SearchQuery(
          filterExpression: Meili.geoRadius(
            (lat: 45.472735, lng: 9.184019),
            2000,
          ),
        ),
      );
  ```
</CodeGroup>

<CodeGroup>
  ```json theme={null}
  [
    {
      "id": 1,
      "name": "Nàpiz' Milano",
      "address": "Viale Vittorio Veneto, 30, 20124, Milan, Italy",
      "type": "pizza",
      "rating": 9,
      "_geo": {
        "lat": 45.4777599,
        "lng": 9.1967508
      }
    },
    {
      "id": 3,
      "name": "Artico Gelateria Tradizionale",
      "address": "Via Dogana, 1, 20123 Milan, Italy",
      "type": "ice cream",
      "rating": 10,
      "_geo": {
        "lat": 45.4632046,
        "lng": 9.1719421
      }
    }
  ]
  ```
</CodeGroup>

## Sort results by distance

Use `_geoPoint` in the [`sort` search parameter](/reference/api/search/search-with-post#body-sort) to order results by proximity. The following example sorts restaurants by distance from the Eiffel Tower:

<CodeGroup>
  ```bash cURL theme={null}
  curl \
    -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
    -H 'Content-type:application/json' \
    --data-binary '{ "sort": ["_geoPoint(48.8561446,2.2978204):asc"] }'
  ```

  ```javascript JS theme={null}
  client.index('restaurants').search('', {
    sort: ['_geoPoint(48.8561446, 2.2978204):asc'],
  })
  ```

  ```python Python theme={null}
  client.index('restaurants').search('', {
    'sort': ['_geoPoint(48.8561446,2.2978204):asc']
  })
  ```

  ```php PHP theme={null}
  $client->index('restaurants')->search('', [
    'sort' => ['_geoPoint(48.8561446,2.2978204):asc']
  ]);
  ```

  ```java Java theme={null}
  SearchRequest searchRequest = SearchRequest.builder().q("").sort(new String[] {"_geoPoint(48.8561446,2.2978204):asc"}).build();
  client.index("restaurants").search(searchRequest);
  ```

  ```ruby Ruby theme={null}
  client.index('restaurants').search('', { sort: ['_geoPoint(48.8561446, 2.2978204):asc'] })
  ```

  ```go Go theme={null}
  resp, err := client.Index("restaurants").Search("", &meilisearch.SearchRequest{
    Sort: []string{
      "_geoPoint(48.8561446,2.2978204):asc",
    },
  })
  ```

  ```csharp C# theme={null}
  SearchQuery filters = new SearchQuery()
  {
      Sort = new string[] { "_geoPoint(48.8561446,2.2978204):asc" }
  };

  var restaurants = await client.Index("restaurants").SearchAsync<Restaurant>("", filters);
  ```

  ```rust Rust theme={null}
  let results: SearchResults<Restaurant> = client
    .index("restaurants")
    .search()
    .with_sort(&["_geoPoint(48.8561446, 2.2978204):asc"])
    .execute()
    .await
    .unwrap();
  ```

  ```swift Swift theme={null}
  let searchParameters = SearchParameters(
      query: "",
      sort: ["_geoPoint(48.8561446, 2.2978204):asc"]
  )
  client.index("restaurants").search(searchParameters) { (result: Result<Searchable<Restaurant>, Swift.Error>) in
      switch result {
      case .success(let task):
        print(task)
      case .failure(let error):
        print(error)
      }
    }
  ```

  ```dart Dart theme={null}
  await client.index('restaurants').search(
      '', SearchQuery(sort: ['_geoPoint(48.8561446, 2.2978204):asc']));
  ```
</CodeGroup>

<CodeGroup>
  ```json theme={null}
  [
    {
      "id": 2,
      "name": "Bouillon Pigalle",
      "address": "22 Bd de Clichy, 75018 Paris, France",
      "type": "french",
      "rating": 8,
      "_geo": {
        "lat": 48.8826517,
        "lng": 2.3352748
      }
    },
    …
  ]
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Filter by radius" href="/capabilities/geo_search/how_to/filter_by_geo_radius">
    Find results within a circular area around a point
  </Card>

  <Card title="Filter by bounding box" href="/capabilities/geo_search/how_to/filter_by_geo_bounding_box">
    Find results within a rectangular area
  </Card>

  <Card title="Filter by polygon" href="/capabilities/geo_search/how_to/filter_by_geo_polygon">
    Find results within a custom polygon shape
  </Card>

  <Card title="Sort by distance" href="/capabilities/geo_search/how_to/sort_by_geo_point">
    Rank results by proximity to a location
  </Card>

  <Card title="Use GeoJSON format" href="/capabilities/geo_search/how_to/use_geojson_format">
    Index complex geometries with the GeoJSON standard
  </Card>
</CardGroup>
