私が持っています
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);
});
};
Yosvel Quintero's answerに関連しますが、私にとってはうまくいきませんでした:
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)
})
Mongooseによると docs :
Model.findByIdAndUpdate()
「一致するドキュメントを検索し、更新引数に従って更新し、オプションを渡し、見つかったドキュメント(ある場合)をコールバックに返します。」
オプションでupsertをtrueに設定します。
upsert:bool-オブジェクトが存在しない場合は作成します。デフォルトはfalseです。
Model.findByIdAndUpdate(id, { $set: { name: 'SOME_VALUE' }}, { upsert: true }, callback)
約束する 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);
}
各スキーマは、そのモデルのインスタンスと 静的メソッド を定義できます。静的はメソッドとほとんど同じですが、モデルに直接存在する関数を定義できます
静的メソッド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);
});
_async/await
_を使用した1行のソリューション:
const page = Page.findOne({}).then(p => p || p.create({})
約束の使用:
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*/ )
モデルに静的メソッドを追加したくない場合は、少なくともこれらのコールバックがネストされたレベルを持たないように、いくつかのものを移動しようとすることができます。
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;
});
}
});
}