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?
Cheers.
In MongoDB, upsert is an option that is used for update operation e.g. update(), findAndModify(), etc. Or in other words, upsert is a combination of update and insert (update + insert = upsert).
The way we do this is by $project ing our documents and using the $concat string aggregation operator to return the concatenated string. You then iterate the cursor and use the $set update operator to add the new field to your documents using bulk operations for maximum efficiency.
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:
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.
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
db.events.find() { "_id" : ObjectId("5113c82dd28c4e8b79971add"), "coords" : { "lat" : 1, "lon" : 2 }, "someotherdata" : [ ] } { "_id" : ObjectId("5113c82ed28c4e8b79971ade"), "coords" : { "lat" : 4, "lon" : 1 }, "someotherdata" : [ ] }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With