sql >> Database >  >> NoSQL >> MongoDB

MongoDB- Invoegen als het niet bestaat, anders overslaan

Je hebt hier twee echte keuzes, afhankelijk van hoe je dingen wilt aanpakken:

  1. Gebruik upsert functionaliteit van MongoDB om in wezen "op te zoeken" als de belangrijkste gegevens bestaan. Zo niet, dan geef je alleen gegevens door aan $setOnInsert en dat raakt niets anders.

  2. Gebruik "Niet-Geordende" bewerkingen in bulk. De hele reeks updates gaat door, zelfs als er een fout wordt geretourneerd, maar de foutrapporten zijn precies dat en alles wat geen fout is, wordt uitgevoerd.

Heel voorbeeld:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var testSchema = new Schema({
  "_id": Number,
  "name": String
},{ "_id": false });

var Test = mongoose.model('Test',testSchema,'test');

mongoose.connect('mongodb://localhost/test');

var data = [
  { "_id": 1, "name": "One" },
  { "_id": 1, "name": "Another" },
  { "_id": 2, "name": "Two" }
];

async.series(
  [
    // Start fresh
    function(callback) {
      Test.remove({},callback);
    },

    // Ordered will fail on error. Upserts never fail!
    function(callback) {
      var bulk = Test.collection.initializeOrderedBulkOp();
      data.forEach(function(item) {
        bulk.find({ "_id": item._id }).upsert().updateOne({
          "$setOnInsert": { "name": item.name }
        });
      });
      bulk.execute(callback);
    },

    // All as expected
    function(callback) {
      Test.find().exec(function(err,docs) {
        console.log(docs)
        callback(err);
      });
    },


    // Start again
    function(callback) {
      Test.remove({},callback);
    },

    // Unordered will just continue on error and record an error
    function(callback) {
      var bulk = Test.collection.initializeUnorderedBulkOp();
      data.forEach(function(item) {
        bulk.insert(item);
      });
      bulk.execute(function(err,result) {
        callback(); // so what! Could not care about errors
      });
    },


    // Still processed the whole batch
    function(callback) {
      Test.find().exec(function(err,docs) {
        console.log(docs)
        callback(err);
      });
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

Merk op dat de "gewijzigde actie" in de huidige stuurprogramma's is dat de resultaatreactie op .execute() zal een foutobject retourneren dat moet worden gegenereerd, waar eerdere releases dit niet deden met "Niet-geordende" bewerkingen.

Dit maakt het absoluut noodzakelijk dat uw code nooit vertrouwt op de err alleen geretourneerd, en u zou het geretourneerde result moeten invoeren in plaats daarvan voor de volledige classificatie van fouten.

Desalniettemin, wanneer niet besteld, gaat de batch door tot het einde, hoeveel fouten er ook optreden. Dingen die geen fout zijn, worden normaal begaan.

Dit komt echt neer op "is volgorde belangrijk". Als dat zo is, dan heb je "Geordende" bewerkingen nodig en kun je dubbele sleutels alleen vermijden door "upserts" te gebruiken. Gebruik anders "ongeordend", maar let op de foutmeldingen en wat ze eigenlijk betekenen.

Ook bij gebruik van .collection om het onderliggende verzamelobject van de basisdriver te krijgen om "Bulk" -bewerkingen in te schakelen, zorg er dan altijd voor dat een van de "een" mongoose-methode altijd eerst is aangeroepen.

Zonder dat is er geen gegarandeerde verbinding met de database met de native driver-methoden zoals deze wordt afgehandeld voor de mangoest-methoden, dus de bewerking zal mislukken omdat er geen verbinding is.

Het alternatief om eerst een mangoestmethode te "afvuren", is om uw app-logica in een gebeurtenislistener voor de verbinding te verpakken:

mongoose.connection.on("open",function(err) {
    // app logic in here
})


  1. Waarom geeft PyMongo 3 ServerSelectionTimeoutError?

  2. Verbinding geweigerd door Docker-container

  3. MongoDB Sleutel invoegen met '$' (dollar)

  4. MongoDB:is het veilig om de ID van het document in het openbaar te gebruiken?