Reputation: 590
I need to query a MongoDb collection with this structure:
{
"_id" : ObjectId("53cfc8bf8f11381e28373153"),
"name" : "0700452",
"description" : "",
"styleurl" : "#style00001",
"point" : {
"altitudemode" : "clampToGround",
"coordinates" : "11.8263919657018, 41.2129293739724, 1.02757364822173"
}
}
The type of query I need to do is based on 2dsphere indexed search, but when I tried this one:
db.coordinatas.find({ $near : { type:'Point', point:{coordinates:"15.8263919657018, 41.2129293739724"}, $maxDistance : 100 }});
I get an error:
error: {
"$err" : "can't find any special indices: 2d (needs index), 2dsphere (needs index), for: { $near: { type: \"Point\", point: { coordinates: \"15.8263919657018, 41.2129293739724\" }, $maxDistance: 100.0 } }",
"code" : 13038
}
Contrary of what the error says the index is there:
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "test4-dev.coordinatas",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"coordinates" : "2dsphere"
},
"ns" : "test4-dev.coordinatas",
"name" : "coordinates"
}
]
This probably happens because the 2dsphere index need an array of two coordinates.
I was thinking maybe I can restructure the collection in this new format:
{
"_id" : ObjectId("53cfc8bf8f11381e28373153"),
"name" : "0700452",
"coordinates": [11.8263919657018, 41.2129293739724]
}
and query the collection in this way :
db.coordinatas.find({ $near : {type:'Point', coordinates:[11.8263919657018, 41.2129293739724], $maxDistance : 100 }});
How can I change the format of the old collection in the new one ?
Upvotes: 1
Views: 231
Reputation: 3879
As documented in this page:
The [
2dsphere
] index supports data stored as both GeoJSON objects and as legacy coordinate pairs. The index supports legacy coordinate pairs by converting the data to the GeoJSON Point type.
If you're going to transform you data, I would recommend you transform it to a GeoJSON point, which would look something like this:
{ loc: { type: "Point", coordinates: [ 11.8263919657018, 41.2129293739724 ] } }
In order to do so, you would have to run a script in which you do the following:
Once all the documents are transformed, you can drop you old index and build the new index using the new field name.
UPDATE:
As a reference, this is a way to update the collection through the mongo
shell. You might find it useful.
// Iterate through all the documents and set the new field
// with the GeoJSON point using the old coordinates string.
db.coords.find().forEach(function(doc) {
var id = doc._id,
coords = doc.point.coordinates.split(", ");
db.coords.update({ "_id" : id }, { $set : { "point.loc.type": "Point", "point.loc.coordinates": [ coords[0], coords[1] ] } });
});
// Unset the old field from all the documents
db.coords.update({}, { $unset: { "point.coordinates" : 1 } }, { "multi": true });
Upvotes: 1
Reputation: 69663
MongoDBs string operations aren't advanced enough to do this completely on the database, so you will have to do it with a little program in the MongoDB shell. Alternatively, you can do this in your favorite programming language which has a MongoDB driver.
db.collection.find()
query to get a cursor over every single document in the collectionsave
the document back to the collection (the save function will search for a document with the same _id and update it, when none is found it creates a new document, which will not happen in your case, because you obtained the _id from the database)Upvotes: 0