mongodb type change to array
Starting in Mongo 4.2
, db.collection.update()
can accept an aggregation pipeline, finally allowing the update of a field based on its current value:
// { field: "some text" }
db.collection.update(
{},
[{ $set: { field: ["$field"] } }],
{ multi: true }
)
// { field: [ "some text" ] }
The first part
{}
is the match query, filtering which documents to update (in this case all documents).The second part
[{ $set: { field: { ["$field"] } } }]
is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline).$set
(alias of$addFields
) is a new aggregation operator which in this case replaces the field's value (simply wrapping it into an array). Note howfield
is modified directly based on its own value ($field
).Don't forget
{ multi: true }
(or to useupdateMany
), otherwise only the first matching document will be updated.
Actually, the find( { "jobLocationCity" : { $type : 2 } } ) will not work properly, because if you'll run update script next time, it will treat ['mystring'] elements again as string type.
You should use something like this to prevent it:
db.message_info.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach(
function (x) {
if (!Array.isArray(x.jobLocationCity)){
x.jobLocationCity = [ x.jobLocationCity ];
db.jobs.save(x);
}
}
)
see http://docs.mongodb.org/manual/reference/operators/
Nitin Garg's answer above almost works, except his example converts from a string to a hash, NOT a string to an array.
Taking into account Joel Harris's comments, the proper solution would look like:
db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach( function (x) {
x.jobLocationCity = [ jobLocationCity ];
db.jobs.save(x);
});
Or if using db.eval:
function f() {
db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach( function (x) {
x.jobLocationCity = [ jobLocationCity ];
db.jobs.save(x);
});
}
db.eval(f);