Frage Wie kann String mit Mongo-Aggregation zu Datum konvertieren?


In einer Sammlung speichere ich diese Art von Dokument

{
    "_id" : 1,
    "created_at" : "2016/01/01 12:10:10",
    ...
}.
{
    "_id" : 2,
    "created_at" : "2016/01/04 12:10:10",
    ...
}

Ich möchte Dokumente finden, die "creared_at"> 01.01.2016 unter Verwendung der Aggregationspipeline haben.

Hat jemand eine Lösung, um "created_at" auf den neuesten Stand zu bringen, damit er sich in der Aggregation vorstellen kann?


5
2018-01-17 10:54


Ursprung


Antworten:


Wie Sie bereits erwähnt haben, müssen Sie zuerst Ihr Schema ändern, damit das created_at Englisch: www.doc-o-matic.com/webhelp/Tdlg.html Feld enthält Datumsobjekte im Gegensatz zu String, wie es in der aktuellen Situation der Fall ist find() Methode oder das Aggregations-Framework. Ersteres wäre der einfachste Weg.

Umwandeln created_at Bis zum Datum müssen Sie den Cursor wiederholen, der von der zurückgegeben wird find() Methode mit dem forEach() Methode, innerhalb der Schleife konvertieren die created_at Feld zu einem Date-Objekt und aktualisieren Sie das Feld dann mit dem $set Operator.

Nutzen Sie die Vorteile der Massen-API Für Bulk-Updates, die eine bessere Leistung bieten, da Sie die Vorgänge in 1000er-Schritten an den Server senden, was Ihnen eine bessere Leistung bringt, da Sie nicht jede Anfrage an den Server senden, sondern nur einmal alle 1000 Anfragen.

Im Folgenden wird dieser Ansatz veranschaulicht. Im ersten Beispiel wird die in MongoDB-Versionen verfügbare Massen-API verwendet >= 2.6 and < 3.2. Es aktualisiert alle die Dokumente in der Sammlung durch Ändern der created_at Felder zu Datum Felder:

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

Das nächste Beispiel gilt für die neue MongoDB-Version 3.2 was hat seit hat die Bulk-API veraltet und stellte einen neueren Satz von apis zur Verfügung bulkWrite():

var cursor = db.collection.find({"created_at": {"$exists": true, "$type": 2 }}),
    bulkOps = [];

cursor.forEach(function (doc) { 
    var newDate = new Date(doc.created_at);
    bulkOps.push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "created_at": newDate } } 
            }         
        }           
    );   

    if (bulkOps.length === 1000) {
        db.collection.bulkWrite(bulkUpdateOps);
        bulkOps = [];
    }
});         

if (bulkOps.length > 0) { db.collection.bulkWrite(bulkOps); }

Sobald die Schemaänderung abgeschlossen ist, können Sie Ihre Sammlung nach dem Datum abfragen:

var dt = new Date("2016/01/01");
db.collection.find({ "created_at": { "$gt": dt } });

Wenn Sie eine Abfrage über das Aggregationsframework durchführen möchten, führen Sie die folgende Pipeline aus, um das gewünschte Ergebnis zu erhalten. Es nutzt die $match Operator, der dem ähnlich ist find() Methode:

var dt = new Date("2016/01/01");
db.collection.aggregate([
    {
        "$match": { "created_at": { "$gt": dt } }
    }
])

6
2018-01-17 11:20



Wenn wir Dokumente haben:

db.doc.save({ "_id" : 1, "created_at" : "2016/01/01 12:10:10" })
db.doc.save({ "_id" : 2, "created_at" : "2016/01/04 12:10:10" })

Einfache Abfrage:

db.doc.find({ "created_at" : {"$lte": Date()} })

Gesamte Abfrage:

db.doc.aggregate([{ 
     "$match": { "created_at": { "$lte": Date() } }
}])
  • Date () -Methode, die das aktuelle Datum als String zurückgibt.
  • neuer Date () - Konstruktor, der ein Date-Objekt mithilfe des ISODate () - Wrappers zurückgibt.
  • ISODate () -Konstruktor, der ein Date-Objekt mit dem ISODate () zurückgibt   Verpackung.

Weitere Informationen zum Datumstyp Hier und Hier


1
2018-01-17 21:31



Alle oben genannten Antworten verwenden cursors aber mongodb empfiehlt immer zu verwenden aggregation Pipeline. Mit dem Neuen $dateFromString im mongodb 3.6Es ist ziemlich einfach. https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/

db.collection.aggregate([
    {$project:{ created_at:{$dateFromString:{dateString:'$created_at'}}}}
])

1
2018-04-09 06:40