J'essaie de changer le type d'un champ à partir de la coque mongo.
Je fais ça ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Mais ça ne marche pas!
J'essaie de changer le type d'un champ à partir de la coque mongo.
Je fais ça ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Mais ça ne marche pas!
Réponses:
La seule façon de modifier le $type
des données est d'effectuer une mise à jour sur les données où les données ont le type correct.
Dans ce cas, il semble que vous essayez de changer le $type
de 1 (double) à 2 (chaîne) .
Chargez simplement le document à partir de la base de données, effectuez le cast ( new String(x)
), puis enregistrez à nouveau le document.
Si vous devez le faire par programme et entièrement à partir du shell, vous pouvez utiliser la find(...).forEach(function(x) {})
syntaxe.
En réponse au deuxième commentaire ci-dessous. Remplacez le champ bad
par un nombre par 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);
});
new String(x.bad)
crée une collection de chaînes avec une x.bad
valeur d' élément d'index 0 . Variante ""+x.bad
, décrite par Simone, fonctionne comme vous le souhaitez - crée une valeur de chaîne au lieu de Int32
db.questions.find({_id:{$type:16}}).forEach( function (x) { db.questions.remove({_id:x._id},true); x._id = ""+x._id; db.questions.save(x); });
Convertir le champ String en Integer:
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 le 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);
});
NumberLong
comme ici:db.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
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 la conversion de chaîne en double.
obj.my_value= parseInt(obj.my_value, 10);
Pour le flotteur:
obj.my_value= parseFloat(obj.my_value);
radix
- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
new NumberInt()
Au départ 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:
"a"
en chaîne lorsque sa valeur est un double, cela correspond aux éléments pour lesquels "a"
est de type 1
(double)).La deuxième partie [{ $set: { a: { $toString: "$a" } } }]
est le pipeline d'agrégation de mise à jour:
$set
est un nouvel opérateur d'agrégation ( Mongo 4.2
) qui dans ce cas modifie un champ."$set"
la valeur de "a"
à "$a"
converti "$toString"
.Mongo 4.2
référencer le document lui-même lors de sa mise à jour: la nouvelle valeur de "a"
est basée sur la valeur existante de "$a"
."$toString"
quel 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.
Dans le cas où votre casting est pas de deux à chaîne, vous avez le choix entre les 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 le remplacer { $toString: "$a" }
par une $convert
opération: { $convert: { input: "$a", to: 2 } }
où la valeur de to
se trouve dans ce tableau :
db.collection.update(
{ a : { $type: 1 } },
[{ $set: { a: { $convert: { input: "$a", to: 2 } } } }],
{ multi: true }
)
db.collection.updateMany( { a : { $type: 1 } }, [{ $set: { a: { $toString: "$a" } } }] )
- le multi : true
peut être évité en utilisantupdateMany
toutes les réponses jusqu'à présent utilisent une version de forEach, itérant sur 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 une étape $ out comme:
l'étape $ out remplace de manière atomique la collection existante par la 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',
},
]);
Pour convertir un champ de type chaîne en champ de date, vous devez itérer le curseur renvoyé par la find()
méthode à l'aide de la forEach()
méthode, dans la boucle, convertir le champ en objet Date, puis mettre à jour le champ à l'aide de l' $set
opérateur.
Profitez de l'utilisation de l' API en masse pour les mises à jour en masse qui offrent de meilleures performances car vous enverrez les opérations au serveur par lots de, disons 1000, ce qui vous donne de meilleures performances car vous n'envoyez pas toutes les demandes au serveur, une seule fois dans chaque 1000 demandes.
Ce qui suit illustre cette approche, le premier exemple utilise l'API Bulk disponible dans les versions MongoDB >= 2.6 and < 3.2
. Il met à jour tous les documents de la collection en modifiant tous lescreated_at
champs 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 déconseillé l'API Bulk et fourni un ensemble plus récent d' API en 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 });
Pour convertir int32 en chaîne dans mongo sans créer de tableau, ajoutez simplement "" à votre nombre :-)
db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {
x.mynum = x.mynum + ""; // convert int32 to string
db.foo.save(x);
});
Ce qui m'a vraiment aidé à changer le type de l'objet dans MondoDB était juste 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 l'âge est l'objet qui avait une chaîne au lieu d'un entier (int32).
J'ai besoin de changer le type de données de plusieurs champs de la collection, j'ai donc utilisé ce qui suit pour apporter plusieurs changements de type de données dans la collection de documents. Répondez à une vieille question mais peut être utile pour les 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);
});
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);
});
demo change le type de champ mid de string à mongo objectId en utilisant mongoose
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.
J'utilise ce script dans la console mongodb pour les conversions de chaîne à flotteur ...
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)
);
}
dans mon cas, j'utilise 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}});
});
}
toString
un champ de document, voici le petit programme que j'ai créé / utilisé .