MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB :copie d'un tableau vers un autre tableau dans le même document

Pour des données relativement petites, vous pouvez réaliser ce qui précède en itérant la collection à l'aide d'un snapshot avec le curseur forEach() méthode et mise à jour de chaque document comme suit :

db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 
    db.wholesalers.updateOne(
        { "_id": doc._id },
        { "$set": { "brandsNetherlands": doc.brands } }
    );
});

Bien que cela soit optimal pour les petites collections, les performances avec les grandes collections sont considérablement réduites car parcourir un grand ensemble de données et envoyer chaque opération de mise à jour par requête au serveur entraîne une pénalité de calcul.

Le Bulk() L'API vient à la rescousse et améliore considérablement les performances puisque les opérations d'écriture ne sont envoyées au serveur qu'une seule fois en masse. L'efficacité est atteinte puisque la méthode n'envoie pas chaque demande d'écriture au serveur (comme avec la déclaration de mise à jour actuelle dans le forEach() loop) mais seulement une fois sur 1000 requêtes, ce qui rend les mises à jour plus efficaces et plus rapides qu'actuellement.

En utilisant le même concept ci-dessus avec le forEach() boucle pour créer les lots, nous pouvons mettre à jour la collection en bloc comme suit.

Dans cette démonstration, le Bulk() API disponible dans les versions MongoDB >= 2.6 and < 3.2 utilise le initializeUnorderedBulkOp() méthode pour exécuter en parallèle, ainsi que dans un ordre non déterministe, les opérations d'écriture dans les batchs :

var vrac =db.wholesalers.initializeUnorderedBulkOp(), compteur =0 ; // compteur pour garder une trace de la taille de la mise à jour du lot

db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 

    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "brandsNetherlands": doc.brands } 
    });

    counter++; // increment counter
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.wholesalers.initializeUnorderedBulkOp();
    }
});

L'exemple suivant s'applique à la nouvelle version de MongoDB 3.2 qui a depuis déprécié le Bulk() API et a fourni un ensemble d'API plus récent en utilisant bulkWrite() .

Il utilise les mêmes curseurs que ci-dessus mais crée les tableaux avec les opérations en bloc en utilisant le même forEach() la méthode du curseur pour pousser chaque document d'écriture en masse vers le tableau. Étant donné que les commandes d'écriture ne peuvent pas accepter plus de 1 000 opérations, il est nécessaire de regrouper les opérations pour avoir au maximum 1 000 opérations et de réinitialiser le tableau lorsque la boucle atteint l'itération 1 000 :

var cursor = db.wholesalers.find({
         "brands": { "$exists": true, "$type": 4 } 
    }),
    bulkUpdateOps = [];

cursor.snapshot().forEach(function(doc){ 
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "brandsNetherlands": doc.brands } }
         }
    });

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

if (bulkUpdateOps.length > 0) { db.wholesalers.bulkWrite(bulkUpdateOps); }