web-dev-qa-db-ja.com

Mongooseで見つけるか作成する

私が持っています

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

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)
})
9
David Joos

Mongooseによると docs

previous SO answer

Model.findByIdAndUpdate()

「一致するドキュメントを検索し、更新引数に従って更新し、オプションを渡し、見つかったドキュメント(ある場合)をコールバックに返します。」

オプションでupsertをtrueに設定します。

upsert:bool-オブジェクトが存在しない場合は作成します。デフォルトはfalseです。

Model.findByIdAndUpdate(id, { $set: { name: 'SOME_VALUE' }}, { upsert: true  }, callback)
19
Julian Boyce

約束する 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);
}
9
Ninh Pham

各スキーマは、そのモデルのインスタンスと 静的メソッド を定義できます。静的はメソッドとほとんど同じですが、モデルに直接存在する関数を定義できます

静的メソッド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);
});
8
Yosvel Quintero

_async/await_を使用した1行のソリューション:

const page = Page.findOne({}).then(p => p || p.create({})

3
Pooya

約束の使用:

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*/ )
0
flakolefluk

モデルに静的メソッドを追加したくない場合は、少なくともこれらのコールバックがネストされたレベルを持たないように、いくつかのものを移動しようとすることができます。

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

 }
0
Umakant Mane