web-dev-qa-db-fra.com

Incrémentation automatique Mongoose

Selon cet article de mongodb il est possible d’auto incrémenter un champ et je voudrais utiliser la méthode de collecte des compteurs.

Le problème avec cet exemple est que des milliers de personnes ne saisissent pas les données de la base de données à l'aide de la console mongo. Au lieu de cela, j'essaie d'utiliser de la mangouste.

Donc, mon schéma ressemble à ceci:

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

J'ai créé la collection de compteurs dans la même base de données et ajouté une page avec l'identifiant _id de 'entityId'. À partir de là, je ne suis pas sûr de savoir comment utiliser mangouste pour mettre à jour cette page et obtenir le numéro incrémenté.

Il n'y a pas de schéma pour les compteurs et j'aimerais qu'il en reste ainsi, car il ne s'agit pas vraiment d'une entité utilisée par l'application. Il ne doit être utilisé que dans les schémas pour incrémenter automatiquement les champs.

15
HMR

Voici un exemple d'utilisation du champ à incrémentation automatique dans Mongoose:

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

Vous pouvez utiliser le package mongoose-auto-increment comme suit:

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

Vous devez seulement initialiser la autoIncrement une fois.

25
moorara

La réponse la plus votée ne fonctionne pas. C'est le correctif:

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

Les paramètres options vous donnent le résultat de la mise à jour et créent un nouveau document s'il n'existe pas .. Vous pouvez vérifier ici le document officiel.

Et si vous avez besoin d’un index trié, cochez doc

11
cluny85

Je sais que cela a déjà beaucoup de réponses, mais je partagerais ma solution qui est courte et facile à comprendre pour l'OMI:

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

Assurez-vous que entitySchema._id a type:Number. Version Mongoose: 5.0.1.

6
Simon

Je ne souhaitais utiliser aucun plugin (une dépendance supplémentaire, initialisant la connexion mongodb en plus de celle que j’utilise dans le server.js, etc ...) donc j’ai fait un module supplémentaire, je peux l’utiliser dans n’importe quel schéma et même, je songe à supprimer un document de la base de données.

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

Et comment l'utiliser:

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;

J'espère que ça vous aide.

(Si cela ne va pas, merci de me le dire. Je n'ai eu aucun problème avec cela, mais pas un expert)

2
Alberto Rubio

Vous pouvez également utiliser des paquets externes fournis par mangouste (facile à comprendre).

mongoose sequence plugin

1
PALLAMOLLA SAI

J'utilise ensemble @ cluny85 et @edtech . Mais je ne termine pas la finition ce problème.

counterModel.findByIdAndUpdate({_id: 'aid'}, {$inc: { seq: 1} }, function(error,counter){ Mais dans la fonction "pre ('save ...) puis la réponse du compteur de mise à jour se termine après la sauvegarde du document . Je ne mets donc pas à jour le compteur à document.

Veuillez vérifier à nouveau toutes les réponses. Merci.

Pardon. Je ne peux pas ajouter de commentaire. Parce que je suis novice.

0
nguyen.thom

Donc, en combinant plusieurs réponses, voici ce que j’ai utilisé:

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
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