mongodb type change to array

2019-01-14 12:23发布

问题:

I have a field in mongodb that's a string. {"field": "some text"}, I want to convert them all into arrays. {"field": ["some text"]}

I know I can just loop through all the documents, get the field, then update, but I'm wondering if there's a cleaner way.

Thanks.

回答1:

You could do it in a Reduce function of map/reduce to keep all the processing in mongodb. Essentially you would use map/reduce to put the results into a new collection and then you could copy them back to the old collection (or delete old one and rename the new one). This has the advantage of keeping everything inside of mongo.

Update: Another option might be for you to use db.eval for this. db.eval executes on the server so the updates would be done on the server without any traffic/latency.

I think the only other option is as you described - do it on the client by querying and updating each one.



回答2:

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);


回答3:

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/



回答4:

try this instead

This is to change the type of a field from string to array in mongoDB

db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).forEach( function (x) {
    x.jobLocationCity = {"Location":x.jobLocationCity};
    db.jobs.save(x);
});

see the link for $type's possible values



回答5:

but I'm wondering if there's a cleaner way..

The short answer is no.

MongoDB does not have any single operation or command to perform a "change type".

The quickest way to do this is likely to use one of the drivers and make the change. You can use the shell and write a for loop, but in terms of raw speed, the other drivers may be faster.

That stated, the slowest part of the process is going to be loading all of the data from disk into memory to be changed and then flushing that data back to disk. This would be true even with a magic "change type" command.