programing

Mongoose를 사용하여 검색 또는 생성

instargram 2023. 6. 21. 22:10
반응형

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

Mongoose 문서에 따라:

이전 SO 답변에 따름

Model.FindByIdAndUpdate()

"일치하는 문서를 찾아서 업데이트 인수에 따라 업데이트하고 옵션을 전달한 후 발견된 문서(있는 경우)를 콜백으로 반환합니다."

true로 설정된 옵션에서 다음을 수행합니다.

upsert:bool - 개체가 없으면 개체를 만듭니다. 기본값은 false입니다.

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

요스벨 퀸테로의 답변과 관련하여, 저는 잘 되지 않았습니다.

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

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

각 스키마는 모델에 대한 인스턴스(instance) 및 정적 메서드를 정의할 수 있습니다.통계량은 방법과 거의 동일하지만 모형에 직접 존재하는 함수를 정의할 수 있습니다.

정적 방법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:

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

정적 메서드를 모델에 추가하지 않으려면 다음과 같은 모든 콜백 중첩 수준을 사용하지 않고 몇 가지 항목을 이동할 수 있습니다.

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

여기에 게시된 솔루션은 필드 또는 필드 조합에 고유 인덱스가 있을 때 이 패턴이 가장 일반적이라는 것을 무시합니다.이 솔루션은 고유한 인덱스 위반 오류를 올바르게 고려합니다.

mongoose.plugin((schema) => {
  schema.statics.findOrCreate = async function findOrCreate(key, attrs) {
    try {
      return await this.create({ ...attrs, ...key });
    } catch (error) {
      const isDuplicateOnThisKey =
        error.code === 11000 &&
        Object.keys(error.keyPattern).sort().join(',') ===
          Object.keys(key).sort().join(',');
      if (isDuplicateOnThisKey) {
        const doc = await this.findOne(error.keyValue);
        doc.set(attrs);
        return await doc.save();
      }
      throw error;
    }
  };
});

용도:

await Post.findOrCreate({ slug: 'foobar' }, { title: 'Foo Bar', body });

이것을 시도해 보세요.

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

 }

언급URL : https://stackoverflow.com/questions/40102372/find-one-or-create-with-mongoose

반응형