Geospatial Indexing with a simple key first

2019-05-17 01:26发布

After reading about MongoDB and Geospatial Indexing

I was amazed that it did not support compound keys not starting with the 2d index.

I dont know if I would gain anything on it, but right now the mssql solution is just as slow/fast.

SELECT TOP 30 * FROM Villages WHERE SID = 10 ORDER BY (math to calc radius from the center point)

This works, but is slow because it not smart enough to use a index so it has to calc the radius for all villages with that SID.

So in Mongo I wanted to create an index like: {sid: 1, loc: "2d"} so I could filter out alot from the start.

I'm not sure there are any solutions for this. I thought about creating a collection for each sid since they don't share any information. But what are the disadvantages of this? Or is this how people do it ?

Update

The maps are flat: 800, 800 to -800,-800, villages are places from the center of the map and out. There are about 300 different maps which are not related, so they could be in diff collections, but not sure about the overhead.

If more information is need, please let me know.

What I have tried

> var res = db.Villages.find({sid: 464})
> db.Villages.find({loc: {$near: [50, 50]}, sid: {$in: res}})
error: { "$err" : "invalid query", "code" : 12580 }
>

Also tried this

db.Villages.find({loc: {$near: [50, 50]}, sid: {$in: db.Villages.find({sid: 464}, {sid: 1})}})
error: { "$err" : "invalid query", "code" : 12580 }

I'm not really sure what I'm doing wrong, but its probably somthing about the syntax. Confused here.

1条回答
Anthone
2楼-- · 2019-05-17 01:37

As you stated already Mongodb cannot accept location as secondary key in geo index. 2d has to be first in index. So you are out of luck here in changing indexing patterns here.

But there is a workaround, instead the compound geo index you can create two separate indexes on sid and one compound index with loc and sid

  db.your_collection.ensureIndex({sid : 1})
  db.your_collection.ensureIndex({loc : '2d',sid:1})

or two separate indexes on sid and loc

  db.your_collection.ensureIndex({sid : 1})
  db.your_collection.ensureIndex({loc : '2d'})

(am not sure which of the above one is efficient, you can try it yourself)

and you can make two different queries to get the results filterd by sid first and the location next, kinda like this

  res = db.your_collection.find({sid:10})
  //get all the ids from the res (res_ids)
  //and query by location using the ids
  db.your_collection.find({loc:{ $near : [50,50] } ,sid : {$in : res_ids}})  
查看更多
登录 后发表回答