Meilisearch 允许您根据搜索结果的地理位置进行筛选和排序。当您只想获取特定区域内的结果,或根据结果与特定位置的距离进行排序时,这会非常有用。
由于 Meilisearch 在以下版本(v0.27、v0.28 和 v0.29)中允许格式不正确的 _geo
字段,请确保 _geo
字段遵循正确的格式。
为基于位置的搜索准备文档
为了开始根据文档的地理位置进行筛选和排序,您必须确保它们包含有效的 _geo
字段。
_geo
是一个保留字段。如果您将其包含在文档中,Meilisearch 要求其值符合特定格式。
当使用 JSON 和 NDJSON 时,_geo
必须包含一个带有两个键(lat
和 lng
)的对象。这两个字段都必须包含浮点数或字符串,分别表示纬度和经度。
{
…
"_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
与 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
列表中
每当您更新 filterableAttributes
时,Meilisearch 都会重建您的索引。根据数据集的大小,这可能需要相当长的时间。
您可以在我们的专用筛选指南中阅读有关配置 filterableAttributes
的更多信息。
使用 filter
搜索参数以及 _geoRadius
或 _geoBoundingBox
。这些是特殊的筛选规则,可确保 Meilisearch 只返回位于特定地理区域内的结果。
_geoRadius
_geoRadius(lat, lng, distance_in_meters)
_geoBoundingBox
_geoBoundingBox([{lat}, {lng}], [{lat}, {lng}])
使用我们的示例数据集,我们可以使用 _geoRadius
搜索米兰市中心附近的餐饮场所
我们还使用 _geoBoundingBox
进行类似的查询
[
{
"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
与其他筛选器结合使用。我们可以缩小之前的搜索范围,使其只包含披萨店
[
{
"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
排序结果
在使用地理搜索进行排序之前,您必须将 _geo
属性添加到 sortableAttributes
列表
在此处阅读有关 sortableAttributes
的更多信息。
_geoPoint
排序函数可以像任何其他排序规则一样使用。我们可以根据文档与埃菲尔铁塔的距离进行排序
使用我们的餐馆数据集,结果如下所示
[
{
"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
在与其他排序规则一起使用时也有效。我们可以根据餐馆与埃菲尔铁塔的距离和它们的评分进行排序
[
{
"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
}
}
]