Meilisearch 允许您根据地理位置筛选和排序结果。当您只想在特定区域内获得结果,或者根据与特定位置的距离对结果进行排序时,这非常有用。
由于 Meilisearch 在以下版本(v0.27、v0.28 和 v0.29)中允许格式不正确的 _geo 字段,请确保 _geo 字段遵循正确的格式。
要开始根据地理位置筛选和排序文档,您必须确保它们包含有效的 _geo 字段。 _geo 是一个保留字段。如果您将其包含在文档中,Meilisearch 希望其值符合特定格式。 使用 JSON 和 NDJSON 时,_geo 必须包含一个具有两个键的对象:latlng。这两个字段都必须包含浮点数或表示纬度和经度的字符串:
{

  "_geo": {
    "lat": 0.0,
    "lng": "0.0"
  }
}

示例

假设我们有一个包含几家餐厅的 JSON 数组
[
  {
    "id": 1,
    "name": "Nàpiz' Milano",
    "address": "Viale Vittorio Veneto, 30, 20124, Milan, Italy",
    "type": "pizza",
    "rating": 9
  },
  {
    "id": 2,
    "name": "Bouillon Pigalle",
    "address": "22 Bd de Clichy, 75018 Paris, France",
    "type": "french",
    "rating": 8
  },
  {
    "id": 3,
    "name": "Artico Gelateria Tradizionale",
    "address": "Via Dogana, 1, 20123 Milan, Italy",
    "type": "ice cream",
    "rating": 10
  }
]
一旦我们添加地理定位数据,我们的餐厅数据集就变成这样了
[
  {
    "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
    }
  }
]
尝试索引一个或多个包含格式不正确的 _geo 值的文档的数据集将导致 Meilisearch 抛出 invalid_document_geo_field 错误。在这种情况下,更新将失败,并且不会添加或修改任何文档。

_geo 与 CSV 结合使用

如果您的数据集格式为 CSV,则文件头必须具有 _geo 列。数据集中的每一行都必须包含一列,其中包含逗号分隔的字符串,指示纬度和经度
"id:number","name:string","address:string","type:string","rating:number","_geo:string"
"1","Nàpiz Milano","Viale Vittorio Veneto, 30, 20124, Milan, Italy","pizzeria",9,"45.4777599,9.1967508"
"2","Bouillon Pigalle","22 Bd de Clichy, 75018 Paris, France","french",8,"48.8826517,2.3352748"
"3","Artico Gelateria Tradizionale","Via Dogana, 1, 20123 Milan, Italy","ice cream",10,"48.8826517,2.3352748"

使用 _geoRadius_geoBoundingBox 过滤结果

您可以使用 _geo 数据来过滤查询,以便只接收位于给定地理区域内的结果。

配置

要根据位置过滤结果,您必须将 _geo 属性添加到 filterableAttributes 列表中
curl \
  -X PUT 'MEILISEARCH_URL/indexes/restaurants/settings/filterable-attributes' \
  -H 'Content-type:application/json' \
  --data-binary '["_geo"]'
每当您更新 filterableAttributes 时,Meilisearch 都会重建您的索引。根据数据集的大小,这可能需要相当长的时间。 您可以在我们的专用过滤指南中阅读有关配置 filterableAttributes 的更多信息。

用法

filter 搜索参数_geoRadius_geoBoundingBox 一起使用。这些是特殊的过滤规则,可确保 Meilisearch 只返回位于特定地理区域内的结果。

_geoRadius

_geoRadius(lat, lng, distance_in_meters)

_geoBoundingBox

_geoBoundingBox([{lat}, {lng}], [{lat}, {lng}])

示例

使用我们的示例数据集,我们可以使用 _geoRadius 搜索米兰市中心附近的餐饮场所
curl \
  -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
  -H 'Content-type:application/json' \
  --data-binary '{ "filter": "_geoRadius(45.472735, 9.184019, 2000)" }'
我们还使用 _geoBoundingBox 进行类似的查询
curl \
  -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
  -H 'Content-type:application/json' \
  --data-binary '{ "filter": "_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])" }'
[
  {
    "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
    }
  }
]
还可以将 _geoRadius_geoBoundingBox 与其他过滤器结合使用。我们可以缩小之前的搜索范围,使其只包含披萨店
curl \
  -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
  -H 'Content-type:application/json' \
  --data-binary '{ "filter": "_geoRadius(45.472735, 9.184019, 2000) AND type = pizza" }'
[
  {
    "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
    }
  }
]
_geo_geoDistance_geoPoint 不是有效的过滤规则。尝试将它们中的任何一个与 filter 搜索参数一起使用将导致 invalid_search_filter 错误。

使用 _geoPoint 排序结果

配置

在将地理搜索用于排序之前,您必须将 _geo 属性添加到 sortableAttributes 列表
curl \
  -X PUT 'MEILISEARCH_URL/indexes/restaurants/settings/sortable-attributes' \
  -H 'Content-type:application/json' \
  --data-binary '["_geo"]'
在此处阅读有关 sortableAttributes 的更多信息。

用法

_geoPoint(0.0, 0.0):asc

示例

_geoPoint 排序函数可以像任何其他排序规则一样使用。我们可以根据文档与埃菲尔铁塔的距离来排序文档
curl \
  -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
  -H 'Content-type:application/json' \
  --data-binary '{ "sort": ["_geoPoint(48.8561446,2.2978204):asc"] }'
使用我们的餐厅数据集,结果如下所示
[
  {
    "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
    }
  },
  {
    "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
    }
  }
]
_geoPoint 也适用于与其他排序规则一起使用。我们可以根据餐厅与埃菲尔铁塔的距离和评分对餐厅进行排序
curl \
  -X POST 'MEILISEARCH_URL/indexes/restaurants/search' \
  -H 'Content-type:application/json' \
  --data-binary '{
    "sort": [
      "_geoPoint(48.8561446,2.2978204):asc",
      "rating:desc"
    ]
  }'
[
  {
    "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
    }
  },
  {
    "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
    }
  }
]
© . This site is unofficial and not affiliated with Meilisearch.