Próbuję zmienić typ pola z wnętrza powłoki mangusty.
Robię to ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Ale to nie działa!
Próbuję zmienić typ pola z wnętrza powłoki mangusty.
Robię to ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Ale to nie działa!
Odpowiedzi:
Jedynym sposobem zmiany $type
danych jest aktualizacja danych, które mają odpowiedni typ.
W tym przypadku wygląda na to, że próbujesz zmienić $type
z 1 (double) na 2 (string) .
Po prostu załaduj dokument z bazy danych, wykonaj cast ( new String(x)
), a następnie ponownie zapisz dokument.
Jeśli chcesz to zrobić programowo i całkowicie z poziomu powłoki, możesz użyć find(...).forEach(function(x) {})
składni.
W odpowiedzi na drugi komentarz poniżej. Zmień pole bad
z liczby na ciąg w kolekcji 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)
tworzy kolekcję Strings z wartością 0-indeksu x.bad
. Wariant ""+x.bad
opisany przez Simone działa zgodnie z życzeniem - tworzy wartość String zamiast 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); });
Konwertuj pole typu String na liczbę całkowitą:
db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
obj.field-name = new NumberInt(obj.field-name);
db.db-name.save(obj);
});
Konwertuj pole typu Integer na ciąg:
db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
obj.field-name = "" + obj.field-name;
db.db-name.save(obj);
});
NumberLong
jak tutaj:db.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
Dla konwersji ciągów na int.
db.my_collection.find().forEach( function(obj) {
obj.my_value= new NumberInt(obj.my_value);
db.my_collection.save(obj);
});
Dla ciągów do podwójnej konwersji.
obj.my_value= parseInt(obj.my_value, 10);
Dla pływaka:
obj.my_value= parseFloat(obj.my_value);
radix
- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ...
new NumberInt()
Zaczynając Mongo 4.2
, db.collection.update()
może akceptować potok agregacji, a na końcu zezwalając na aktualizację pola na podstawie jego własnej wartości:
// { 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" }
Pierwsza część { a : { $type: 1 } }
to zapytanie dopasowujące:
"a"
na łańcuch, gdy jego wartość jest double, dopasowuje to elementy, dla których "a"
jest typu 1
(double)).Druga część [{ $set: { a: { $toString: "$a" } } }]
to potok agregacji aktualizacji:
$set
jest nowym operatorem agregacji ( Mongo 4.2
), który w tym przypadku modyfikuje pole."$set"
wartość "a"
do "$a"
konwersji "$toString"
.Mongo 4.2
odniesienia się do samego dokumentu podczas jego aktualizacji: nowa wartość dla "a"
jest oparta na istniejącej wartości "$a"
."$toString"
który jest nowym operatorem agregacji wprowadzonym w Mongo 4.0
.Nie zapomnij { multi: true }
, w przeciwnym razie zaktualizowany zostanie tylko pierwszy pasujący dokument.
W przypadku, gdy nie jest to odlew z double na łańcuch, masz wybór pomiędzy różnymi operatorami konwersji wprowadzonych Mongo 4.0
takich jak $toBool
, $toInt
...
A jeśli nie jest dedykowany konwerter do docelowego typu, można wymienić { $toString: "$a" }
z $convert
pracy: { $convert: { input: "$a", to: 2 } }
gdzie wartość to
można znaleźć w tej tabeli :
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" } } }] )
- multi : true
można tego uniknąć używającupdateMany
wszystkie dotychczasowe odpowiedzi używają jakiejś wersji forEach, iterując po wszystkich elementach kolekcji po stronie klienta.
Możesz jednak użyć przetwarzania po stronie serwera MongoDB, używając potoku agregacji i etapu $ out jako:
etap $ out atomowo zastępuje istniejącą kolekcję nową kolekcją wyników.
przykład:
db.documents.aggregate([
{
$project: {
_id: 1,
numberField: { $substr: ['$numberField', 0, -1] },
otherField: 1,
differentField: 1,
anotherfield: 1,
needolistAllFieldsHere: 1
},
},
{
$out: 'documents',
},
]);
Aby przekonwertować pole typu string na pole Date , należałoby wykonać iterację kursora zwróconego przez find()
metodę przy użyciu forEach()
metody, w pętli przekonwertować pole na obiekt Date, a następnie zaktualizować pole za pomocą $set
operatora.
Skorzystaj z funkcji Bulk API do zbiorczych aktualizacji, które oferują lepszą wydajność, ponieważ będziesz wysyłać operacje na serwer partiami, powiedzmy 1000, co zapewnia lepszą wydajność, ponieważ nie wysyłasz każdego żądania do serwera, tylko raz na 1000 wniosków.
Poniższy przykład ilustruje to podejście, pierwszy przykład używa interfejsu Bulk API dostępnego w wersjach MongoDB >= 2.6 and < 3.2
. Aktualizuje wszystkie dokumenty w kolekcji, zmieniając wszystkie created_at
pola na pola daty:
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(); }
Następny przykład dotyczy nowej wersji MongoDB, 3.2
która od tego czasu wycofała Bulk API i udostępniła nowszy zestaw API przy użyciu 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 });
Aby przekonwertować int32 na string w mongo bez tworzenia tablicy, po prostu dodaj "" do swojego numeru :-)
db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {
x.mynum = x.mynum + ""; // convert int32 to string
db.foo.save(x);
});
To, co naprawdę pomogło mi zmienić typ obiektu w MondoDB, to ta prosta linia, być może wspomniana wcześniej tutaj ...:
db.Users.find({age: {$exists: true}}).forEach(function(obj) {
obj.age = new NumberInt(obj.age);
db.Users.save(obj);
});
Użytkownicy to moja kolekcja, a wiek to obiekt, który miał ciąg znaków zamiast liczby całkowitej (int32).
Muszę zmienić typ danych wielu pól w kolekcji, więc użyłem poniższego, aby dokonać wielu zmian typu danych w kolekcji dokumentów. Odpowiedz na stare pytanie, ale może być pomocne dla innych.
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.
Spróbuj tego zapytania ...
db.collectionName.find().forEach( function (x) {
x.FieldName = parseInt(x.FieldName);
db.collectionName.save(x);
});
demo zmienia typ pola mid ze string na mongo objectId używając 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 to kolejny przykład takich stylów jak
Number, string, boolean, które mają nadzieję, że odpowiedź pomoże komuś innemu.
Używam tego skryptu w konsoli mongodb do ciągów znaków do konwersji typu float ...
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); } );
A ten w 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)
);
}
w moim przypadku używam następujących
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
z polem dokumentu, oto mały program, który stworzyłem / użyłem .