web-dev-qa-db-fra.com

MongoDB: Comment changer le type d'un champ?

Il y a déjà une question dans Stackoverflow, très similaire à ma question… .. Le fait est que la réponse à cette question était pour un pilote Java, j'essaie de le faire dans le shell.

Je fais ça ...

db.meta.update({'fields.properties.default': { $type : 1 }}, {'fields.properties.default': { $type : 2 }})

Cela ne marche pas!

130
J. Quintas

Le seul moyen de modifier le $type des données consiste à effectuer une mise à jour des données pour lesquelles le type de données est correct.

Dans ce cas, il semble que vous tentiez de changer le $typede 1 (double) à 2 (chaîne) .

Donc, chargez simplement le document à partir de la base de données, effectuez la conversion (new String(x)) puis enregistrez à nouveau le document.

Si vous devez le faire entièrement à partir du shell par programme, vous pouvez utiliser la syntaxe find(...).forEach(function(x) {}).


En réponse au deuxième commentaire ci-dessous. Modifiez le champ bad d'un nombre à une chaîne dans la collection foo.

db.foo.find( { 'bad' : { $type : 1 } } ).forEach( function (x) {   
  x.bad = new String(x.bad); // convert field to string
  db.foo.save(x);
});
179
Gates VP

Convertir le champ Chaîne en Entier:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) { 
    obj.field-name = new NumberInt(obj.field-name);
    db.db-name.save(obj);
});

Convertir un champ entier en chaîne:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
    obj.field-name = "" + obj.field-name;
    db.db-name.save(obj);
});
145
Simone

Pour la conversion de chaîne en int. 

db.my_collection.find().forEach( function(obj) {
    obj.my_value= new NumberInt(obj.my_value);
    db.my_collection.save(obj);
});

Pour que la chaîne double la conversion. 

    obj.my_value= parseInt(obj.my_value, 10);

Pour float:

    obj.my_value= parseFloat(obj.my_value);
34
David Dehghan
db.coll.find().forEach(function(data) {
    db.coll.update({_id:data._id},{$set:{myfield:parseInt(data.myfield)}});
})
18
Russell

Pour convertir int32 en chaîne dans mongo sans créer de tableau ajoutez simplement "" à votre numéro :-)

db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {   
  x.mynum = x.mynum + ""; // convert int32 to string
  db.foo.save(x);
});
4
Giulio Roggero

Ce qui m'a vraiment aidé à changer le type d'objet dans MondoDB, c'est cette simple ligne, peut-être mentionnée auparavant ici ...:

db.Users.find({age: {$exists: true}}).forEach(function(obj) {
    obj.age = new NumberInt(obj.age);
    db.Users.save(obj);
});

Les utilisateurs sont ma collection et age est l'objet qui avait une chaîne au lieu d'un entier (int32).

3
Felipe

Pour convertir un champ de type chaîne en champ de date, vous devez itérer le curseur renvoyé par la méthode find() à l'aide de la méthode forEach(), dans le boucle convertit le champ en objet Date, puis met à jour le champ à l’aide de l’opérateur $set.

Tirez parti de la API EN BLOC pour les mises à jour en masse qui offrent de meilleures performances, car vous enverrez les opérations au serveur par lots de 1000, ce qui vous donne de meilleures performances, car vous n'envoyez pas. chaque demande au serveur, juste une fois sur 1000 demandes. 

Ce qui suit illustre cette approche. Le premier exemple utilise l'API en bloc disponible dans les versions de MongoDB >= 2.6 and < 3.2. Il met à jour tous les documents de la collection en modifiant tous les champs created_at en champs de date:

var bulk = db.collection.initializeUnorderedBulkOp(),
    counter = 0;

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
    var newDate = new Date(doc.created_at);
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "created_at": newDate}
    });

    counter++;
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }

L'exemple suivant s'applique à la nouvelle version de MongoDB 3.2 qui a depuis OBSOL&EGRAVE;TE L'API EN BLOC et a fourni un jeu plus récent d'apis utilisant bulkWrite():

var bulkOps = [];

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) { 
    var newDate = new Date(doc.created_at);
    bulkOps.Push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "created_at": newDate } } 
            }         
        }           
    );     
})

db.collection.bulkWrite(bulkOps, { "ordered": true });
2
chridam

jusqu'à présent, toutes les réponses utilisent une version de forEach, en parcourant tous les éléments de la collection côté client.

Cependant, vous pouvez utiliser le traitement côté serveur de MongoDB en utilisant un pipeline agrégé et $ out stage as:

l'étape $ out remplace atomiquement la collection existante par le nouvelle collection de résultats.

exemple:

db.documents.aggregate([
         {
            $project: {
               _id: 1,
               numberField: { $substr: ['$numberField', 0, -1] },
               otherField: 1,
               differentField: 1,
               anotherfield: 1,
               needolistAllFieldsHere: 1
            },
         },
         {
            $out: 'documents',
         },
      ]);
2
user3616725

À partir de _Mongo 4.2_, db.collection.update() peut accepter un pipeline d'agrégation, permettant enfin la mise à jour d'un champ en fonction de sa propre valeur:

_// { a: "45", b: "x" }
// { a:  53,  b: "y" }
db.collection.update(
  { a : { $type: 1 } },
  [{ $set: { a: { $toString: "$a" } } }],
  { multi: true }
)
// { a: "45", b: "x" }
// { a: "53", b: "y" }
_
  • La première partie _{ a : { $type: 1 } }_ est la requête de correspondance:

    • Il filtre les documents à mettre à jour.
    • Dans ce cas, puisque nous voulons convertir _"a"_ en chaîne lorsque sa valeur est double, cela correspond aux éléments pour lesquels _"a"_ est de type _1_ (double)).
    • Cette table fournit les codes représentant les différents types possibles.
  • La deuxième partie _[{ $set: { a: { $toString: "$a" } } }]_ est le pipeline d'agrégation de mises à jour:

    • Notez les crochets indiquant que cette requête de mise à jour utilise un pipeline d'agrégation.
    • $set est un nouvel opérateur d'agrégation (_Mongo 4.2_) qui, dans ce cas, modifie un champ.
    • Cela peut être simplement lu comme _"$set"_ la valeur de _"a"_ à _"$a"_ converti _"$toString"_.
    • Ce qui est vraiment nouveau ici, c'est de pouvoir référencer le document lui-même lors de sa mise à jour dans _Mongo 4.2_: la nouvelle valeur de _"a"_ est basée sur la valeur existante de _"$a"_.
    • Notez également "$toString" qui est un nouvel opérateur d'agrégation introduit dans _Mongo 4.0_.
  • N'oubliez pas _{ multi: true }_, sinon seul le premier document correspondant sera mis à jour.


Si votre distribution n’est pas de double en chaîne, vous avez le choix entre différents opérateurs de conversion introduits dans _Mongo 4.0_, tels que $toBool , $toInt , ...

Et s'il n'y a pas de convertisseur dédié pour votre type ciblé, vous pouvez remplacer _{ $toString: "$a" }_ par une opération _$convert_: _{ $convert: { input: "$a", to: 2 } }_ où la valeur de to peut être trouvée dans ceci table :

_db.collection.update(
  { a : { $type: 1 } },
  [{ $set: { a: { $convert: { input: "$a", to: 2 } } } }],
  { multi: true }
)
_
2
Xavier Guihot

Je dois changer le type de données de plusieurs champs de la collection. J'ai donc utilisé ce qui suit pour modifier plusieurs types de données dans la collection de documents. Répondez à une vieille question mais peut être utile pour d’autres.

db.mycoll.find().forEach(function(obj) { 

    if (obj.hasOwnProperty('phone')) {
        obj.phone = "" + obj.phone;  // int or longint to string
    }

    if (obj.hasOwnProperty('field-name')) {
     obj.field-name = new NumberInt(obj.field-name); //string to integer
    }

    if (obj.hasOwnProperty('cdate')) {
        obj.cdate = new ISODate(obj.cdate); //string to Date
    }

    db.mycoll.save(obj); 
});
1
Aakash
You can easily convert the string data type to numerical data type.
Don't forget to change collectionName & FieldName.
for ex : CollectionNmae : Users & FieldName : Contactno.

Essayez cette requête ..

db.collectionName.find().forEach( function (x) {
x.FieldName = parseInt(x.FieldName);
db.collectionName.save(x);
});
1
Amarendra Kumar

dans mon cas, j'utilise le suivant

function updateToSting(){
  var collection = "<COLLECTION-NAME>";
  db.collection(collection).find().forEach(function(obj) {
    db.collection(collection).updateOne({YOUR_CONDITIONAL_FIELD:obj.YOUR_CONDITIONAL_FIELD},{$set:{YOUR_FIELD:""+obj.YOUR_FIELD}});
  });
}
0
Renish Gotecha

J'utilise ce script dans la console mongodb pour string afin de convertir les conversions ...

db.documents.find({ 'fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.fwtweaeeba = parseFloat( obj.fwtweaeeba ); 
        db.documents.save(obj); } );    

db.documents.find({ 'versions.0.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[0].content.fwtweaeeba = parseFloat( obj.versions[0].content.fwtweaeeba ); 
        db.documents.save(obj); } );

db.documents.find({ 'versions.1.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[1].content.fwtweaeeba = parseFloat( obj.versions[1].content.fwtweaeeba );  
        db.documents.save(obj); } );

db.documents.find({ 'versions.2.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[2].content.fwtweaeeba = parseFloat( obj.versions[2].content.fwtweaeeba );  
        db.documents.save(obj); } );

Et celui-ci en php)))

foreach($db->documents->find(array("type" => "chair")) as $document){
    $db->documents->update(
        array('_id' => $document[_id]),
        array(
            '$set' => array(
                'versions.0.content.axdducvoxb' => (float)$document['versions'][0]['content']['axdducvoxb'],
                'versions.1.content.axdducvoxb' => (float)$document['versions'][1]['content']['axdducvoxb'],
                'versions.2.content.axdducvoxb' => (float)$document['versions'][2]['content']['axdducvoxb'],
                'axdducvoxb' => (float)$document['axdducvoxb']
            )
        ),
        array('$multi' => true)
    );


}
0
user3469031

demo change le type de champ entre string et mongo objectId en utilisant mangouste 

 Post.find({}, {mid: 1,_id:1}).exec(function (err, doc) {
             doc.map((item, key) => {
                Post.findByIdAndUpdate({_id:item._id},{$set:{mid: mongoose.Types.ObjectId(item.mid)}}).exec((err,res)=>{
                    if(err) throw err;
                    reply(res);
                });
            });
        });

Mongo ObjectId est juste un autre exemple de styles tels que

Nombre, chaîne, booléen qui espère que la réponse aidera quelqu'un d'autre.

0
Tran Hoang Hiep