0 votes
in MongoDB by
MongoDB: Updating documents using data from the same document

1 Answer

0 votes
by
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.
...