在Mongodb上使用带地理空间索引的全文搜索
比如说,我想开发一个android应用程序,允许用户搜索离你最近的酒店。这在当今的应用程序中非常常见,例如AirBnb 这是我正在使用的数据集:在Mongodb上使用带地理空间索引的全文搜索,mongodb,full-text-search,mongodb-query,geospatial,Mongodb,Full Text Search,Mongodb Query,Geospatial,比如说,我想开发一个android应用程序,允许用户搜索离你最近的酒店。这在当今的应用程序中非常常见,例如AirBnb 这是我正在使用的数据集: { "name" : "The Most Amazing Hotel", "city" : "India", "type": "Point" "coord": [ -56.16082, 61.15392 ] } { "name" : "The Most Incredi
{
"name" : "The Most Amazing Hotel",
"city" : "India",
"type": "Point"
"coord": [
-56.16082,
61.15392
]
}
{
"name" : "The Most Incredible Hotel",
"city" : "India",
"type": "Point"
"coord": [
-56.56285,
61.34590
]
}
{
"name" : "The Fantastic GuestHouse",
"city" : "India",
"type": "Point"
"coord": [
-56.47085,
61.11357
]
}
现在,我想在名称
字段上创建一个文本索引,以便它按名称搜索,然后根据坐标按地理空间索引排序
因此,如果我搜索“最多”一词,它将按名称搜索“最多”一词,并返回最近的酒店,其中包含“最多”一词
mongodb甚至支持这种类型的搜索吗
我在这里阅读mongodb指南:
复合文本索引不能包含任何其他特殊索引类型,
例如多键或地理空间索引字段
据我所知,我并没有创建复合文本索引。这是一个简单的文本索引,这意味着我只为
名称
字段而不是城市
和名称
字段编制文本索引。有一种公平的情况,你根本不需要这个,因为很难证明这样一个索引的用例是合理的我认为“搜索酒店”并不是“文本”和“地理空间”搜索的结合
事实上,“大多数人”会寻找接近某个地点的东西,或者更可能接近他们想去的不同地点,作为他们主要标准的一部分,然后其他“赢家”可能会更重视“成本”、“评级”、“品牌”、“设施”,甚至可能更接近餐馆等
将“文本搜索”添加到该列表是一件非常不同的事情,在这个特定的应用程序中可能没有多大实际用途
尽管如此,这可能值得一些解释,这里有一些概念需要理解,至少对于这个用例来说,这两个概念没有真正的“啮合”
固定模式
首先,我想建议稍微“调整”一下您的数据模式:
{
“名称”:“最令人惊叹的酒店”,
“城市”:“印度”,
“地点”:{
“类型”:“点”,
“坐标”:[
72.867804,
19.076033
]
}
}
这至少提供了“location”
作为有效的GeoJSON对象进行索引,而且您通常希望使用GeoJSON而不是传统的坐标对,因为它确实为查询和存储提供了更多选项,而且距离标准化为米,而不是全球范围内相等的“弧度”
为什么他们不一起工作
因此,您的阅读基本上是正确的,因为您不能同时使用多个特殊索引。首先看一下复合索引定义:
db.hotels.createIndex({“name”:“text”,“location”:“2dsphere”})
{
“ok”:0,
“errmsg”:“错误的索引键模式{name:\'text\”,位置:\'2dsphere\”}:不能对单个索引使用多个索引插件。”,
“代码”:67}
所以这是不可能的。即使单独考虑:
db.hotels.createIndex({“name”:“text”})
db.hotels.createIndex({“location”:“2dsphere”})
然后尝试执行查询:
db.hotels.find({
“地点”:{
“$nearSphere”:{
“$geometry”:{
“类型”:“点”,
“坐标”:[
72.867804,
19.076033
]
}
}
},
“$text”:{“$search”:“惊人”}
})
错误:命令失败:{
“waitedMS”:数字长(0),
“ok”:0,
“errmsg”:“不允许在同一查询中使用文本和地理位置”,
“代码”:2
}:未定义
这实际上支持了为什么不能用三种方式在复合索引中定义它的原因:
$或条件,您基本上回到点1,在这里,即使应用“索引交集”,这种“特殊”索引也有另一个属性,它们必须在“顶层”应用“以允许选择索引。将它们包装在$或中意味着MongoDB不能这样做,因此不允许这样做
db.hotels.aggregate([
{“$geoNear”:{
“近”:{
“类型”:“点”,
“坐标”:[
72.867804,
19.076033
]
},
“球形”:正确,
“最大距离”:5000,
“距离字段”:“距离”,
“查询”:{
“姓名”:/惊人/
}
}}
])
甚至:
db.hotels.find({
“地点”:{
“$nearSphere”:{
“$geometry”:{
“类型”:“点”,
“坐标”:[
72.867804,
19.076033
]
},
“$maxDistance”:5000
}
},
“姓名”:/惊人/
})
或先通过文本搜索:
db.hotels.find({
“$text”:{“$search”:“惊人”},
“地点”:{
“$GEOIN”:{
“$centerSphere”:[[
72.867804,