it-swarm.com.de

Mongoose Auto Inkrement

Laut diesem mongodb-Artikel ist es möglich, ein Feld automatisch zu inkrementieren, und ich möchte die Counter-Collection verwenden.

Das Problem bei diesem Beispiel ist, dass nicht Tausende von Menschen die Daten mithilfe der Mongo-Konsole in die Datenbank eingeben. Stattdessen versuche ich Mungo zu verwenden.

Mein Schema sieht also ungefähr so ​​aus:

var entitySchema = mongoose.Schema({
  testvalue:{type:String,default:function getNextSequence() {
        console.log('what is this:',mongoose);//this is mongoose
        var ret = db.counters.findAndModify({
                 query: { _id:'entityId' },
                 update: { $inc: { seq: 1 } },
                 new: true
               }
        );
        return ret.seq;
      }
    }
});

Ich habe die Zählerauflistung in derselben Datenbank erstellt und eine Seite mit der _id von 'entityId' hinzugefügt. Von hier aus bin ich nicht sicher, wie ich mit Moose die Seite aktualisieren und die steigende Nummer erhalten kann.

Es gibt kein Schema für Zähler, und ich möchte, dass es so bleibt, da dies nicht wirklich eine von der Anwendung verwendete Entität ist. Es sollte nur in den Schemata verwendet werden, um Felder automatisch zu erhöhen.

15
HMR

Hier ein Beispiel, wie Sie ein automatisches Inkrementierungsfeld in Mongoose implementieren können:

var CounterSchema = Schema({
    _id: {type: String, required: true},
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    testvalue: {type: String}
});

entitySchema.pre('save', function(next) {
    var doc = this;
    counter.findByIdAndUpdate({_id: 'entityId'}, {$inc: { seq: 1} }, function(error, counter)   {
        if(error)
            return next(error);
        doc.testvalue = counter.seq;
        next();
    });
});
32
edtech

Sie können mongoose-auto-increment package wie folgt verwenden:

var mongoose      = require('mongoose');
var autoIncrement = require('mongoose-auto-increment');

/* connect to your database here */

/* define your CounterSchema here */

autoIncrement.initialize(mongoose.connection);
CounterSchema.plugin(autoIncrement.plugin, 'Counter');
var Counter = mongoose.model('Counter', CounterSchema);

Sie müssen die autoIncrement nur einmal initialisieren.

25
moorara

Die am meisten gewählte Antwort funktioniert nicht. Dies ist der Fix:

var CounterSchema = new mongoose.Schema({
    _id: {type: String, required: true},
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    sort: {type: String}
});

entitySchema.pre('save', function(next) {
    var doc = this;
    counter.findByIdAndUpdateAsync({_id: 'entityId'}, {$inc: { seq: 1} }, {new: true, upsert: true}).then(function(count) {
        console.log("...count: "+JSON.stringify(count));
        doc.sort = count.seq;
        next();
    })
    .catch(function(error) {
        console.error("counter error-> : "+error);
        throw error;
    });
});

Die options -Parameter geben Ihnen das Ergebnis der Aktualisierung und erstellen ein neues Dokument, falls es nicht vorhanden ist . Sie können hier das offizielle Dokument überprüfen.

Und wenn Sie einen sortierten Index benötigen, überprüfen Sie diesen doc

11
cluny85

Ich weiß, dass dies bereits viele Antworten gibt, aber ich würde meine Lösung weitergeben, die IMO kurz und leicht verständlich ist:

// Use pre middleware
entitySchema.pre('save', function (next) {

    // Only increment when the document is new
    if (this.isNew) {
        entityModel.count().then(res => {
            this._id = res; // Increment count
            next();
        });
    } else {
        next();
    }
});

Stellen Sie sicher, dass entitySchema._idtype:Number. Mongoose-Version hat: 5.0.1.

6
Simon

Ich wollte kein Plugin verwenden (eine zusätzliche Abhängigkeit, die die mongodb-Verbindung außer der Verbindung, die ich in der server.js verwende, usw. initialisiert), also habe ich ein zusätzliches Modul erstellt, ich kann es bei jedem Schema und verwenden Ich denke sogar daran, wenn Sie ein Dokument aus der Datenbank entfernen.

module.exports = async function(model, data, next) {
    // Only applies to new documents, so updating with model.save() method won't update id
    // We search for the biggest id into the documents (will search in the model, not whole db
    // We limit the search to one result, in descendant order.
    if(data.isNew) {
        let total = await model.find().sort({id: -1}).limit(1);
        data.id = total.length === 0 ? 1 : Number(total[0].id) + 1;
        next();
    };
};

Und wie man es benutzt:

const autoincremental = require('../modules/auto-incremental');

Work.pre('save', function(next) {
    autoincremental(model, this, next);
    // Arguments:
    // model: The model const here below
    // this: The schema, the body of the document you wan to save
    // next: next fn to continue
});

const model = mongoose.model('Work', Work);
module.exports = model;

Ich hoffe es hilft dir.

(Wenn dies falsch ist, bitte sagen Sie es mir. Ich hatte keine Probleme damit, aber keinen Experten)

2
Alberto Rubio

Auf andere Weise können Sie externe Pakete verwenden, die von mongoose bereitgestellt werden.

Mungo Sequenz Plugin

1
PALLAMOLLA SAI

Ich benutze zusammen @ cluny85 und @edtech . Aber ich schließe nicht ab diese Ausgaben.

counterModel.findByIdAndUpdate({_id: 'aid'}, {$inc: { seq: 1} }, function(error,counter){ Aber in der Funktion "pre ('save ...)' wird dann die Antwort des Aktualisierungszählers nach dem Speichern des Dokuments beendet.

Bitte überprüfen Sie noch einmal alle Antworten. Danke.

Es tut uns leid. Ich kann keinen Kommentar hinzufügen. Weil ich Neuling bin.

0
nguyen.thom

So kombinierte ich mehrere Antworten, also habe ich am Ende verwendet:

counterModel.js

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

const counterSchema = new Schema(
  {
  _id: {type: String, required: true},
  seq: { type: Number, default: 0 }
  }
);

counterSchema.index({ _id: 1, seq: 1 }, { unique: true })

const counterModel = mongoose.model('counter', counterSchema);

const autoIncrementModelID = function (modelName, doc, next) {
  counterModel.findByIdAndUpdate(        // ** Method call begins **
    modelName,                           // The ID to find for in counters model
    { $inc: { seq: 1 } },                // The update
    { new: true, upsert: true },         // The options
    function(error, counter) {           // The callback
      if(error) return next(error);

      doc.id = counter.seq;
      next();
    }
  );                                     // ** Method call ends **
}

module.exports = autoIncrementModelID;

myModel.js

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

const autoIncrementModelID = require('./counterModel');

const myModel = new Schema({
  id: { type: Number, unique: true, min: 1 },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date },
  someOtherField: { type: String }
});

myModel.pre('save', function (next) {
  if (!this.isNew) {
    next();
    return;
  }

  autoIncrementModelID('activities', this, next);
});

module.exports = mongoose.model('myModel', myModel);
0
Akash Agarwal

Die Antworten scheinen die Reihenfolge zu erhöhen, auch wenn das Dokument bereits ein Feld _id enthält (sortieren, was auch immer). Dies ist der Fall, wenn Sie speichern, um ein vorhandenes Dokument zu aktualisieren. Nein?

Wenn ich recht habe, möchten Sie next () aufrufen, wenn this._id! == 0

Die Mungo-Docs sind sich darüber nicht ganz sicher. Wenn intern eine Aktualisierungsabfrage durchgeführt wird, darf pre ('save' nicht aufgerufen werden.

KLÄRUNG

Es sieht so aus, als würde die Methode 'save' tatsächlich bei Updates aufgerufen.

Ich glaube nicht, dass Sie Ihre Sequenz unnötig erhöhen möchten. Es kostet Sie eine Abfrage und verschwendet die laufende Nummer.

0
mschwartz
var CounterSchema = Schema({
    _id: { type: String, required: true },
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    testvalue: { type: String }
});

entitySchema.pre('save', function(next) {
    if (this.isNew) {
        var doc = this;
        counter.findByIdAndUpdate({ _id: 'entityId' }, { $inc: { seq: 1 } }, { new: true, upsert: true })
            .then(function(count) {
                doc.testvalue = count.seq;
                next();
            })
            .catch(function(error) {
                throw error;
            });
    } else {
        next();
    }
});
0
TinhNQ

Hier ist ein Vorschlag.

Erstellen Sie eine separate Sammlung, die den Maximalwert für eine Modellsammlung enthält

const autoIncrementSchema = new Schema({
    name: String,
    seq: { type: Number, default: 0 }
});

const AutoIncrement = mongoose.model('AutoIncrement', autoIncrementSchema);

Fügen Sie nun für jedes benötigte Schema ein pre-save hook.

Angenommen, der Name der Sammlung lautet Test.

schema.pre('save', function preSave(next) {
    const doc = this;
    if (doc.isNew) {
         const nextSeq = AutoIncrement.findOneAndUpdate(
             { name: 'Test' }, 
             { $inc: { seq: 1 } }, 
             { new: true, upsert: true }
         );

         nextSeq
             .then(nextValue => doc[autoIncrementableField] = nextValue)
             .then(next);
    }
    else next();
 }

Da findOneAndUpdate eine atomic Operation ist, geben keine zwei Aktualisierungen denselben seq Wert zurück. Somit erhält jede Ihrer Einfügungen eine inkrementelle Folge unabhängig von der Anzahl der gleichzeitigen Einfügungen. Dies kann auch auf komplexere Auto-Inkremental-Logik erweitert werden, und die Auto-Inkrement-Sequenz ist nicht auf Number type beschränkt.

Dies ist kein getesteter Code. Testen Sie, bevor Sie es verwenden, bis ich ein Plugin für mongoose erstellt habe.

Update Ich habe festgestellt, dass this Plugin verwandten Ansatz implementiert.

0
MASh