Mongoose: ObjectIdを怜蚌するための最良の方法

䜜成日 2014幎03月12日  Â·  29コメント  Â·  ゜ヌス: Automattic/mongoose

いく぀かのobjectIdを参照ずしお挿入しおいたすが、それらが有効なobjectidであるこずを確認したいず思いたす珟圚、有効なIDでない堎合はクラッシュしたす。

find呌び出しを実行するだけで、それらが有効なオブゞェクトを参照しおいるかどうかを確認しおいたす。

文字列が正しい圢匏であるかどうかを確認するにはどうすればよいですか 文字列が24文字の文字列であるかどうかをチェックするいく぀かのregexを芋たこずがありたすが、そのようなものはハックのようです。 ObjectIdに内郚バリデヌタヌはありたすか 䜿い方がわかりたせんでした。 本圓にありがずう

最も参考になるコメント

これは私のために働きたす

var mongoose = require'./ node_modules / mongoose';
console.logmongoose.Types.ObjectId.isValid;
// [関数isValid]
console.logmongoose.Types.ObjectId.isValid '53cb6b9b4f4ddef1ad47f943';
//true
console.logmongoose.Types.ObjectId.isValid'bleurgh';
// false

党おのコメント29件

私も同じ問題を抱えおいたす。 mongoose.Schema.ObjectId.isValidずmongoose.Types.ObjectId.isValidを詊したしたが、どちらのプロパティにもisValidメ゜ッドがありたせん。 どのようにしおこの問題を解決したのですか たた、mongodbには1぀あり、別のオプションずしお正芏衚珟もありたす。 正芏衚珟を䜿甚したくないし、require'mongodb'する必芁もありたせん

これは私のために働きたす

var mongoose = require'./ node_modules / mongoose';
console.logmongoose.Types.ObjectId.isValid;
// [関数isValid]
console.logmongoose.Types.ObjectId.isValid '53cb6b9b4f4ddef1ad47f943';
//true
console.logmongoose.Types.ObjectId.isValid'bleurgh';
// false

ちなみに、mongodbのメ゜ッドはbson libメ゜ッドであり、nullではない12文字たたは24文字の16進文字列をチェックしたす。これは次のような正芏衚珟です。

var checkForHexRegExp = new RegExp "^ [0-9a-fA-F] {24} $";

だからそれがそこで䜿われおいるならそれはあたりハッキヌになるこずはできたせん

文字列に12文字が含たれおいる堎合、sValidは垞にTrueを返したす

console.logmongoose.Types.ObjectId.isValid "zzzzzzzzzzzz"; //true

「zzzzzzzzzzzz」は技術的には有効なObjectIdであるため、オブゞェクトIDの唯䞀の定矩機胜は、12バむトの長さです。 mongodb / js-bson112を参照しおください。 長さ12のJS文字列は12バむトで、モゞュロナニコヌドの奇劙さを持っおいたす。 長さ24の16進文字列を確認する堎合は、文字列が/^[a-fA-F0-9]{24}$/ず䞀臎するこずを確認しおください。

「zzzzzzzzzzzz」は有効なObjectIdではありたせん。 たずえば、Mongo shell listiongmongodbバヌゞョン-3.0.2

> ObjectId('zzzzzzzzzzzz')
2015-04-29T18:05:20.705+0300 E QUERY    Error: invalid object id: length
    at (shell):1:1
> ObjectId('zzzzzzzzzzzzzzzzzzzzzzzz')
2015-04-29T18:06:09.773+0300 E QUERY    Error: invalid object id: not hex
    at (shell):1:1
> ObjectId('ffffffffffff')
2015-04-29T18:09:17.303+0300 E QUERY    Error: invalid object id: length
    at (shell):1:1
> ObjectId('ffffffffffffffffffffffff')
ObjectId("ffffffffffffffffffffffff")

mongodbシェルのObjectIdコンストラクタヌは、16進文字列のみを受け入れるように蚘述されおいるためです。 これは、BSONタむプのObjectIdではなく、䟿宜䞊のmongoシェルの制限です。 確かに、これは16進文字列がObjectIdの通垞の衚珟方法であるこずを考えるず、やや盎感に反するケヌスですが、それが気に入らない堎合は、正芏衚珟/^[a-fA-F0-9]{24}$/を䜿甚しおください:)

文字列ではなくObjectId自䜓isValidを実行しようずするず、なぜfalseになるのですか ObjectIdは有効なObjectIdであるため、これはtrueを返す必芁がありたすか それは意味がありたせん-オブゞェクトがisValidに枡されおいる堎合は、 .toString()を呌び出したすか

@niftylettuceのコメントは3365で歓迎したす。 今のずころ、 bsonパッケヌゞのObjectId.isValid関数に任せおいたすが、これは、人々がマングヌスのObjectIdをどのように考えおいるかず正確には䞀臎しおいたせん。 ただし、ObjectIdが䞎えられた堎合は、trueを返すためのPRを開きたすが、これは完党に合理的なようです。

ここで少し叀い問題に戻りたす... @atcwells゜リュヌションmongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943')は私にずっおは十分に機胜したすが、オブゞェクトIDが有効かどうかをコントロヌラヌにチェックさせる必芁があるのは少しハッキヌなようです。確かに、䞍正な圢匏のIDをサヌバヌに送信し、クラッシュさせないようにするこずは、かなり䞀般的な䜿甚䟋です。

理想的には、コヌルバックのerrに䜕かを返すだけで、それを正しく凊理し、コントロヌラヌを䜿甚しお正しいHTTPステヌタスを送信できたす。

これがコアの䟿利な機胜ではないナヌスケヌスはありたすか そうでない堎合は、プラグむンを䜜成できる可胜性がありたす。 簡単に怜玢したしたが、仕事をしおいるものは䜕もないようです– https://github.com/CampbellSoftwareSolutions/mongoose-id-validatorは、IDが実際に存圚するこずを怜蚌するためのものですが、これはそうではありたせんここで実行したいのは、キャッチされない゚ラヌが生成されないようにするこずだけです。

珟圚、Expressコントロヌラヌでは、ObjectIdを含むリク゚ストを送信するたびに、たずえばGET to https// myproject / Organisations / {id}を実行するたびに、次のような操䜜を行う必芁がありたす。

if( !mongoose.Types.ObjectId.isValid(id) ){
    return res.sendStatus(400); // They didn't send an object ID
  }

...その前にOrganisation.findOne();を実行したす

かなり定型的なようです。 誰かが私をどこから始めるべきか正しい方向に向けるこずができれば、プラグむンか䜕かを曞いおうれしいです。 それは実際にはスキヌマのものではないので、プラグむンのようには芋えたせん...

@shankiesanする必芁はありたせん。IDが無効な堎合、mongooseはク゚リpromiseを拒吊したす。

var assert = require('assert');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/test');
mongoose.set('debug', true);

var MyModel = mongoose.model('test', new Schema({ name: String }));

MyModel.findOne({ _id: 'invalid' }).exec().catch(error => console.error('error', error));

出力

$ node gh-1959.js 
error { CastError: Cast to ObjectId failed for value "invalid" at path "_id"
    at MongooseError.CastError (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/error/cast.js:19:11)
    at ObjectId.cast (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/schema/objectid.js:147:13)
    at ObjectId.castForQuery (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/schema/objectid.js:187:15)
    at cast (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/cast.js:174:32)
    at Query.cast (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/query.js:2563:10)
    at Query.findOne (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/query.js:1239:10)
    at /home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/query.js:2163:21
    at new Promise.ES6 (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/promise.js:45:3)
    at Query.exec (/home/val/Workspace/10gen/troubleshoot-mongoose/node_modules/mongoose/lib/query.js:2156:10)
    at Object.<anonymous> (/home/val/Workspace/10gen/troubleshoot-mongoose/gh-1959.js:10:37)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
  message: 'Cast to ObjectId failed for value "invalid" at path "_id"',
  name: 'CastError',
  kind: 'ObjectId',
  value: 'invalid',
  path: '_id',
  reason: undefined }
^C
$ 

たた、再プラグむンhttp://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins

ああ、なんおマペットなんだ もちろん、拒吊された玄束を凊理したす... arg、私の脳。 ありがずう@vkarpov15

玄束が頭痛の皮である堎合、コヌルバックも機胜したすMyModel.findOne({ _id: 'invalid' }).exec(error => console.error('error', error)); :)

䞊蚘の12バむトのValeriが蚀ったこずからただ明らかでない堎合は、 ObjectId.isValid()を䜿甚しないでください。 これでかなりよくやけどしたした
ObjectId.isValid('The Flagship') === true

@atcwells非垞に賛成のコメントを曎新しお、そのビットを含めるこずができれば、私が最初にあなたの蚀ったこずに基づいおそれを行っおいたので、他の人がそれを高く評䟡するかもしれないず思いたす ObjectId.isValid('The Flagship') === true

面癜い郚分は次のずおりです。
次のステヌトメントはtrueを返したす
mongoose.Types.ObjectId.isValid "南アフリカ"

私が今のずころ取り組んでいるのは、promisecatchの゚ラヌタむプをチェックするこずです。 'ObjectId'の堎合、404が返されたす。API/ Webサヌビスのコンシュヌマヌにリ゜ヌスが芋぀からないか存圚しないため、404が返されたす。

䟋を参照しおください

  Widget.findByIdAndRemove(resourceId)
    .then((result) => {
      if (!result) {
        let error = new Error('Resource not found');
        error.status = 404;
        next(error);
      } else {
        res.redirect(303, '/');
      }
    })
    .catch((error) => {
      if (error.kind === 'ObjectId') {
        let error = new Error('Resource not found');
        error.status = 404;

        next(error);
      } else {
        next(error);
      }
    });

アップデヌト
これをコントロヌラヌの各ルヌトハンドラヌに远加する代わりに。 グロヌバルキャッチオヌルハンドラヌに远加しおいたす。

䟋を参照しおください

app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  if (err.kind === 'ObjectId') {
    err.status = 404;
  }

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

スキヌマで怜蚌するこずは可胜ですか それを繰り返すのはベストプラクティスではありたせんが、キャスト゚ラヌむベントをログに蚘録したいず思いたす。

MongoDBのみを凊理しおいるのに、isValidの正芏衚珟/ ^ [a-fA-F0-9] {24}$/をmongooseで実装できないのはなぜですか。 これはずおも玛らわしいです。 問題のデバッグに1時間費やすだけで、気付かないほどばかげたこずが刀明したした。

このnpmパッケヌゞhttps://www.npmjs.com/package/valid-objectidを䜿甚するこずをお勧めしたす
それは完璧に動䜜したす

私はこれの回避策を䜜成したした

function isObjectId(value) {
  try {
      const { ObjectId } = mongoose.Types;
      const asString = value.toString(); // value is either ObjectId or string or anything
      const asObjectId = new ObjectId(asString);
      const asStringifiedObjectId = asObjectId.toString();
      return asString === asStringifiedObjectId;
    } catch (error) {
      return false;
    }
}

@mstmustisntè©Šè¡Œ/キャッチする必芁があるず思いたす。倀が「123」の堎合、゚ラヌがスロヌされたす。

それが誰かを助ける堎合に備えお、私は䞊蚘のObjectId.isValid()アプロヌチの適応を行っおきたした。 私のナヌスケヌスでは、IDたたはurl-slugのいずれかでリ゜ヌスを取埗できるようにしたいので、次のようになりたす。

GET /users/59f5e7257a92d900168ce49a ...たたは..。
GET /users/andrew-shankie

...これは私のコントロヌラヌでうたく機胜するこずがわかりたした

  const { id } = req.params;

  const query = {
    $or: [{ slug: id }],
  };

  if (mongoose.Types.ObjectId.isValid(id)) query.$or.push({ _id: id });

  User.findOne(query)
    .exec((err, user) => { ... }

この堎合、12バむトの文字列は匕き続き有効なオブゞェクトIDであり、それを怜玢するず、゚ラヌをスロヌするのではなく、長さがれロの配列が返されたす。 たた、 $orク゚リを䜿甚しおいるため、URLスラッグ他の可胜なオプションで怜玢したす。

最も゚レガントな解決策ではないかもしれたせんが、それは私にずっおはうたくいきたす。

@victorbadilaはい、その通りです。 ヒントを出したした。 コメントを線集したした。実際に䜿甚するコヌドを配眮するだけです。

validator.jsには組み蟌みのisMongoIdメ゜ッドがありたす

私がマングヌスを䜿甚するずきはい぀でも、私は垞にいく぀かの静的ヘルパヌメ゜ッドでそれを拡匵したす

const mongoose = require('mongoose');
const {Types: {ObjectId}} = mongoose;

//Helper to check if an ID is an object ID
mongoose.isObjectId = function(id) {
  return (id instanceof ObjectId);
};

//Helper to validate a string as object ID
mongoose.isValidObjectId = function(str) {
  if (typeof str !== 'string') {
    return false;
  }
  return str.match(/^[a-f\d]{24}$/i);
};

これはデヌタベヌス初期化スクリプトの䞀郚ずしお実行できるため、メ゜ッドはアプリで垞に䜿甚できたす。

ObjectId.isValididがtrueの堎合、new ObjectIdid.toStringの倀ずIDを刀断できたす。

const mongoose = require('mongoose');
const {Types: {ObjectId}} = mongoose;
const validateObjectId = (id) => ObjectId.isValid(id) && (new ObjectId(id)).toString() === id;
このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡