I have a list of documents, each with lat and lon properties (among others).
{ ‘lat’: 1, ‘lon’: 2, someotherdata […] }
{ ‘lat’: 4, ‘lon’: 1, someotherdata […] }
[…]
I want to modify it so that it looks like this:
{ ‘coords’: {‘lat’: 1, ‘lon’: 2}, someotherdata […]}
{ ‘coords’: {‘lat’: 4, ‘lon’: 1}, someotherdata […]}
[…]
So far I’ve got this:
db.events.update({}, {$set : {‘coords’: {‘lat’: db.events.lat, ‘lon’: db.events.lon}}}, false, true)
But it treats the db.events.lat and db.events.lon as strings. How can I reference the document’s properties in MongoDB? Cheers. The $rename operator (introduced a month after this question was posted) makes it really easy to do these kinds of things where you don’t need to modify the values.
Insert some test documents
db.events.insert({ ‘lat’: 1, ‘lon’: 2, someotherdata: [] })
db.events.insert({ ‘lat’: 4, ‘lon’: 1, someotherdata: [] })
use the $rename operator
db.events.update({}, {$rename: {‘lat’: ‘coords.lat’, ‘lon’: ‘coords.lon’}}, false, true)
Results
Skip code block
db.events.find()
{
“_id” : ObjectId(“5113c82dd28c4e8b79971add”),
“coords” : {
“lat” : 1,
“lon” : 2
},
“someotherdata” : [ ]
}
{
“_id” : ObjectId(“5113c82ed28c4e8b79971ade”),
“coords” : {
“lat” : 4,
“lon” : 1
},
“someotherdata” : [ ]
}
Update: If all you have to do is change the structure of a document without changing the values, see gipset’s answer for a nice solution.
According to a (now unavailable) comment on the Update documentation page, you cannot reference the current document’s properties from within an update().
You’ll have to iterate through all the documents and update them like this:
Skip code block
db.events.find().snapshot().forEach(
function (e) {
// update document, using its own properties
e.coords = { lat: e.lat, lon: e.lon };
// remove old properties
delete e.lat;
delete e.lon;
// save the updated document
db.events.save(e);
}
)
Such a function can also be used in a map-reduce job or a server-side db.eval() job, depending on your needs.