MongoDB“无法找到$geoNear查询的索引”

52

我只是想让一个简单的near查询起作用。这是我的文档样例。

{"point": 
  {"type": "Point", 
     "coordinates": [30.443902444762696, -84.27326978424058]}, 
   "created_on": {"$date": 1398016710168}, 
   "radius": 180, 
   "user": {"$oid": "53543188eebc5c0cc416b77c"}, 
   "_id": {"$oid": "53544306eebc5c0ecac6cfba"}, 
   "expires_on": {"$date": 1399831110168}
}

我使用mongod并尝试了以下命令:

db.bar.find({point: {$near: [-84.26060492426588, 30.45023887165371]}});

但我得到了这个错误:

  

错误: {          "$err" : "无法执行查询:处理查询时出错:ns=foo.bar skip=0\nTree: GEONEAR field=point maxdist=1.79769e+308 isNearSphere=0 || First: notFirst: full path: point\nSort: {}\nProj: {}\nplanner 返回错误:无法找到 $geoNear 查询的索引",           "code" : 17007       }

也许我的搜索能力今天不太行,但我找不到任何东西。 我已运行 ensure index 命令。 我的意图是这些是地图位置。

db.bar.ensureIndex({a:1});
db.bar.ensureIndex({geo:"2d"});
7个回答

93

问题在于,您在foo数据库的foo集合上创建了索引,但正在查询bar集合。您需要切换到正确的集合。

根据您插入的文档,您需要为支持geoJson对象添加“2dsphere”索引。此索引需要在文档的“point”元素上。因此,请尝试:

db.bar.createIndex({point:"2dsphere"});

您可以通过提供一个 GeoJson 对象来进行查询,查询方式如下:

db.bar.find(
   { point :
       { $near :
          {
            $geometry : {
               type : "Point" ,
               coordinates : [-84.27326978424058, 30.443902444762696] },
            $maxDistance : 1
          }
       }
    }
)

6
太好了,我使用以下代码解决了我的问题: db.<collection>.ensureIndex({point:"2dsphere"}); - AfromanJ
1
请注意,自 3.0.0 版本起,ensureIndex 已被弃用,并且是 createIndex 的别名(回答已相应地进行了编辑)。 - Yan Foto
关于这个指南针的任何想法:“geoNear命令失败:{ operationTime: Timestamp(1536208908, 1), ok: 0.0, errmsg:“2dsphere index must have spherical: true”,code: 17301,codeName:“Location17301”, $ clusterTime: {clusterTime:Timestamp(1536208908,1),for { “near”:{ “type”:“Point”, “coordinates”:[-73.99279,40.719296] }, “distanceField”:“distance” }` - Hassan Faghihi
@deadManN 在 distanceField: 'distance' 之后添加 spherical: true。这对我有用。 - Daksh
我应该把这行代码放在哪里:db.bar.createIndex({point:"2dsphere"}); - Sanjayrajsinh

12
db.prod.createIndex({ "location": "2d" })

这对我遇到的同样问题有帮助。

其中,prod是我的集合名称,location是存储地理位置(GeoPoint)的列的名称。

关于此问题的讨论可以在这里找到。


感谢您的询问,“location”是存储地理位置(GeoPoint)的列名称。 - Amandeep Rohila
@Krish 请告诉我在哪里放置 createIndex() 这一行?在模式中还是在调用 API 之前或其他地方?我是 Node 的新手。 - Sanjayrajsinh

8
这里似乎有几个问题:
从您展示的数据以及查询信息来看,相关信息包含在字段点(point)中,且格式为GeoJSON。您的索引创建方式:
db.foo.createIndex({geo: "2d"})
并不会“失败”,因为当前没有名为“geo”的字段,而数据应该放在那个位置。如果您使用了正确的字段“point”,则会收到一个错误提示,告诉您这种类型的索引对于GeoJSON数据无效。您需要一个“2dsphere”索引:
db.points.createIndex({ "point": "2dsphere" })
  • 扩展同样的问题,数据再次以GeoJSON格式提供,查询的形式是传统坐标对。您需要更改查询参数,以使其不再失败:
db.points.find({point: {
    $near: {
        $geometry:{ 
            type: "Point", 
            coordinates: [-84.26060492426588, 30.45023887165371]
        }
    }
}})

请参阅$near文档。


非常感谢您详细的解释。通过您的回答,我注意到了我之前出错的地方,我没有正确指向保存路径以创建索引的属性。 - Carlos Bensant

3
除了上面的答案,如果您已经尝试创建索引并且出现了一些语法或字段错误,您可以运行 db.<yourcollection>.dropIndexes(); 清除所有索引并正确重新创建它们。
此外,索引应该在“coordinates”的父级上创建,而不是在“coordinates”本身上创建。
{
   "_id": 59ac03d168eaaa14c2a57a00",
   "location":{
      "type":"Point",
      "coordinates":[
         131.6667,
         57.8368
      ]
   },
   "age":53,
   "username":"Brandi_Greenfelder"
}

db.<您的集合>.createIndex({ location: '2dsphere' });

注意,有"2d"和"2dsphere"两种,使用第二种,因为它是新的。


1
如果您正在使用mongoose进行连接,那么这将是正确的答案:
db.collections.<yourcollection>.createIndex({ location : "2dsphere" })

注意,在集合本身之前有一个“collections”属性。如果不起作用,请在控制台中检查db对象:
console.log(db)

0

如果有人正在从spring-boot-starter-data-mongodb 2迁移到3

他们默认停用了索引的自动配置, 这可能会导致'无法找到 $geoNear 查询的索引'错误

@Configuration
public class Config extends AbstractMongoClientConfiguration {

    @Override
    protected boolean autoIndexCreation() {
        return true;
    }
    // ...
}

0
在我的情况下,我拥有所有必要的内容(有效的GeoJSON,2dsphere索引),但错误仍然出现。问题是,在创建/保存新对象时,我未能在模式定义中为索引指定相同的“2dsphere”值。
// Geo index for new object
const boxSchema = new Schema<IBoxRecord>({
  id: { type: Number, required: true },
  name: { type: String, index: true, required: true },
  location: { 
    type: Object,
    index: "2dsphere", // <--- previously set to `true` by mistake
    require: true 
  }
});

...

// index existing collection
await BoxRecord.collection.createIndex({ location: "2dsphere" });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接