我有
Page.findById(pageId).then(page => {
const pageId = page.id;
..
});
我的问题是,如果没有给出页面ID,它应该在给定条件的情况下获取第一个可用页面,这是由
完成的。Page.findOne({}).then(page => {
const pageId = page.id;
..
});
但是如果找不到页面,它应该创建一个新页面并使用它,这是用
完成的Page.create({}).then(page => {
const pageId = page.id;
..
});
但是如何将所有这些组合成尽可能少的线?
我内心有很多逻辑
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);
});
};
答案 0 :(得分:16)
根据猫鼬docs:
Model.findByIdAndUpdate()
“查找匹配的文档,根据更新arg更新它,传递任何选项,并将找到的文档(如果有的话)返回给回调。”
在选项中将upsert设置为true:
upsert:bool - 如果对象不存在则创建它。默认为false。
Model.findByIdAndUpdate(id, { $set: { name: 'SOME_VALUE' }}, { upsert: true }, callback)
答案 1 :(得分:9)
与 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)
})
答案 2 :(得分:8)
每个Schema都可以为其模型定义实例和static methods。静态与方法几乎相同,但允许定义直接存在于模型上的函数
静态方法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);
});
答案 3 :(得分:8)
承诺async/await
版本。
Page.static('findOneOrCreate', async function findOneOrCreate(condition, doc) {
const one = await this.findOne(condition);
return one || this.create(doc);
});
用法
Page.findOneOrCreate({ id: page.id }, page).then(...).catch(...)
或者
async () => {
const yourPage = await Page.findOneOrCreate({ id: page.id }, page);
}
答案 4 :(得分:3)
使用async/await
的单行解决方案:
const page = Page.findOne({}).then(p => p || p.create({})
答案 5 :(得分:0)
如果您不想在模型中添加静态方法,可以尝试移动一些内容,至少不要使用所有这些回调嵌套级别:
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;
});
}
});
答案 6 :(得分:0)
试试这个..
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;
});
}
});
}
答案 7 :(得分:0)
使用承诺:
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*/ )