J'ai
Page.findById(pageId).then(page => {
const pageId = page.id;
..
});
Mon problème est que si aucun identifiant de page n’est donné, il faut simplement prendre la première page disponible en fonction de certaines conditions, ce qui est fait par
Page.findOne({}).then(page => {
const pageId = page.id;
..
});
mais si aucune page n'est trouvée, il faut créer une nouvelle page et l'utiliser, ce qui est fait avec
Page.create({}).then(page => {
const pageId = page.id;
..
});
Mais comment combiner tout cela avec le moins de lignes possible?
J'ai beaucoup de logique à l'intérieur
page => { ... }
donc je voudrais bien faire cela intelligemment pour pouvoir éviter de le faire comme ça
if (pageId) {
Page.findById(pageId).then(page => {
const pageId = page.id;
..
});
} else {
Page.findOne({}).then(page => {
if (page) {
const pageId = page.id;
..
} else {
Page.create({}).then(page => {
const pageId = page.id;
..
});
}
});
}
Je pense que je pourrais peut-être assigner un statique au schéma avec quelque chose comme
pageSchema.statics.findOneOrCreate = function (condition, doc, callback) {
const self = this;
self.findOne(condition).then(callback).catch((err, result) => {
self.create(doc).then(callback);
});
};
Relatif à Yosvel Quintero's réponse qui n'a pas fonctionné pour moi:
pageSchema.statics.findOneOrCreate = function findOneOrCreate(condition, callback) {
const self = this
self.findOne(condition, (err, result) => {
return result ? callback(err, result) : self.create(condition, (err, result) => { return callback(err, result) })
})
}
Et puis l'utiliser comme:
Page.findOneOrCreate({ key: 'value' }, (err, page) => {
// ... code
console.log(page)
})
Selon le Mongoose docs :
Selon réponse précédente SO
Model.findByIdAndUpdate ()
"Trouve un document correspondant, le met à jour conformément à l'argument de mise à jour, en passant les options et renvoie le document trouvé (le cas échéant) au rappel."
Dans les options, définissez upsert sur true:
upsert: bool - crée l'objet s'il n'existe pas. par défaut à false.
Model.findByIdAndUpdate(id, { $set: { name: 'SOME_VALUE' }}, { upsert: true }, callback)
Chaque schéma peut définir une instance et des méthodes statiques pour son modèle. La statique est à peu près la même chose que les méthodes mais permet de définir des fonctions qui existent directement sur votre modèle.
Méthode statique findOneOrCreate
:
pageSchema.statics.findOneOrCreate = function findOneOrCreate(condition, doc, callback) {
const self = this;
self.findOne(condition, (err, result) => {
return result
? callback(err, result)
: self.create(doc, (err, result) => {
return callback(err, result);
});
});
};
Maintenant, quand vous avez une instance de Page
, vous pouvez appeler findOneOrCreate
:
Page.findOneOrCreate({id: 'somePageId'}, (err, page) => {
console.log(page);
});
Promise async/await
version.
Page.static('findOneOrCreate', async function findOneOrCreate(condition, doc) {
const one = await this.findOne(condition);
return one || this.create(doc);
});
Usage
Page.findOneOrCreate({ id: page.id }, page).then(...).catch(...)
Ou
async () => {
const yourPage = await Page.findOneOrCreate({ id: page.id }, page);
}
Utiliser des promesses:
pageSchema.statics.findOneOrCreate = function(id, cb){
return (id?this.findById(id, cb):this.findOne({}, cb))
.then(page=>page? page : this.create({}, cb))
}
alors vous pouvez l'utiliser comme ceci:
Page.findOneOrCreate(pageId, (err, page)=>{
if(err){
//if theres an error, do something
}
// or do something with the page
})
ou avec des promesses:
Page.findOneOrCreate(id)
.then(page=> /* do something with page*/ )
.catch(err=> /* do something if there's an error*/ )
Si vous ne souhaitez pas ajouter de méthode statique au modèle, vous pouvez essayer de déplacer certaines choses et au moins ne pas avoir tous ces niveaux imbriqués de rappel:
function getPageById (callback) {
Page.findById(pageId).then(page => {
return callback(null, page);
});
}
function getFirstPage(callback) {
Page.findOne({}).then(page => {
if (page) {
return callback(null, page);
}
return callback();
});
}
let retrievePage = getFirstPage;
if (pageId) {
retrievePage = getPageById;
}
retrievePage(function (err, page) {
if (err) {
// @todo: handle the error
}
if (page && page.id) {
pageId = page.id;
} else {
Page.create({}).then(page => {
pageId = page.id;
});
}
});
essaye ça..
var myfunc = function (pageId) {
// check for pageId passed or not
var newId = (typeof pageId == 'undefined') ? {} : {_id:pageId};
Page.findOne(pageId).then(page => {
if (page)
const pageId = page.id;
else { // if record not found, create new
Page.create({}).then(page => {
const pageId = page.id;
});
}
});
}