find一个或用Mongoose创build

我有

Page.findById(pageId).then(page => { const pageId = page.id; .. }); 

我的问题是,如果没有给出页面ID,它应该只是采取第一个可用的页面给出了一些条件,这是由

 Page.findOne({}).then(page => { const pageId = page.id; .. }); 

但如果没有find页面,它应该创build一个新的页面,并使用它,这是完成的

 Page.create({}).then(page => { const pageId = page.id; .. }); 

但是,我怎么把所有这些结合到尽可能less的几行呢?

我有很多逻辑在里面

 page => { ... } 

所以我非常想做这个聪明的,所以我可以避免这样做

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

我想我也许可以分配一个静态类似的东西

 pageSchema.statics.findOneOrCreate = function (condition, doc, callback) { const self = this; self.findOne(condition).then(callback).catch((err, result) => { self.create(doc).then(callback); }); }; 

Yosvel Quintero的答案有关,这对我不起作用:

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

然后像这样使用它:

 Page.findOneOrCreate({ key: 'value' }, (err, page) => { // ... code console.log(page) }) 

每个模式可以为其模型定义实例和静态方法 。 静态方法几乎与方法相同,但允许定义直接存在于模型上的函数

静态方法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); }); }); }; 

现在当你有一个Page的实例,你可以调用findOneOrCreate

 Page.findOneOrCreate({id: 'somePageId'}, (err, page) => { console.log(page); }); 

如果你不想为模型添加一个静态方法,你可以尝试移动一些东西,至less不要有所有这些callback嵌套级别:

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

尝试这个..

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

使用承诺:

 pageSchema.statics.findOneOrCreate = function(id, cb){ return (id?this.findById(id, cb):this.findOne({}, cb)) .then(page=>page? page : this.create({}, cb)) } 

那么你可以像这样使用它:

 Page.findOneOrCreate(pageId, (err, page)=>{ if(err){ //if theres an error, do something } // or do something with the page }) 

或承诺:

 Page.findOneOrCreate(id) .then(page=> /* do something with page*/ ) .catch(err=> /* do something if there's an error*/ )