Mongoose: ObjectId๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•

์— ๋งŒ๋“  2014๋…„ 03์›” 12์ผ  ยท  29์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Automattic/mongoose

์ผ๋ถ€ objectId๋ฅผ ์ฐธ์กฐ๋กœ ์‚ฝ์ž…ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์œ ํšจํ•œ objectid์ธ์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค(์ง€๊ธˆ์€ ์œ ํšจํ•œ ID๊ฐ€ ์•„๋‹ ๋•Œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค).

find() ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์œ ํšจํ•œ ๊ฐœ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด์ด ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์ธ์ง€ ์–ด๋–ป๊ฒŒ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ๋ฌธ์ž์—ด์ด 24์ž ๋ฌธ์ž์—ด์ธ์ง€ ํ™•์ธํ•˜๋Š” ์ผ๋ถ€ ์ •๊ทœ์‹์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ํ•ดํ‚น์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ObjectId์— ๋‚ด๋ถ€ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ผ ์ˆ˜ ์—†์—ˆ๋‹ค. ์ •๋ง ๊ณ ๋งˆ์›Œ!

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

var ๋ชฝ๊ตฌ์Šค = ํ•„์š”('./๋…ธ๋“œ ๋ชจ๋“ˆ/๋ชฝ๊ตฌ์Šค');
console.log(mongoose.Types.ObjectId.isValid);
// [ํ•จ์ˆ˜: isValid]
console.log(mongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943'));
// ์ง„์‹ค
console.log(mongoose.Types.ObjectId.isValid('bleurgh'));
// ๊ฑฐ์ง“

๋ชจ๋“  29 ๋Œ“๊ธ€

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. mongoose.Schema.ObjectId.isValid() ๋ฐ mongoose.Types.ObjectId.isValid()๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ์—๋Š” isValid ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜์…จ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๋˜ํ•œ mongodb์— ํ•˜๋‚˜๊ฐ€ ์žˆ๊ณ  ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์œผ๋กœ ์ •๊ทœ์‹๋„ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •๊ทœ์‹์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์š”๊ตฌํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค('mongodb')

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

var ๋ชฝ๊ตฌ์Šค = ํ•„์š”('./๋…ธ๋“œ ๋ชจ๋“ˆ/๋ชฝ๊ตฌ์Šค');
console.log(mongoose.Types.ObjectId.isValid);
// [ํ•จ์ˆ˜: isValid]
console.log(mongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943'));
// ์ง„์‹ค
console.log(mongoose.Types.ObjectId.isValid('bleurgh'));
// ๊ฑฐ์ง“

๋ง๋ถ™์—ฌ์„œ mongodb์˜ ๋ฉ”์„œ๋“œ๋Š” bson lib ๋ฉ”์„œ๋“œ๋กœ null์ด ์•„๋‹Œ์ง€, 12์ž ๋˜๋Š” 24์ž 16์ง„ ๋ฌธ์ž์—ด์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ •๊ทœ์‹์ž…๋‹ˆ๋‹ค.

var checkForHexRegExp = ์ƒˆ๋กœ์šด RegExp("^[0-9a-fA-F]{24}$");

๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์ด ๊ฑฐ๊ธฐ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด ๋„ˆ๋ฌด ํ•ดํ‚น ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด์— 12์ž๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ sValid()๋Š” ํ•ญ์ƒ True๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

console.log(mongoose.Types.ObjectId.isValid("zzzzzzzzzzzz")); // ์ง„์‹ค

"zzzzzzzzzzzz"๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ ์œ ํšจํ•œ ObjectId์ด๊ธฐ ๋•Œ๋ฌธ์— - ๊ฐœ์ฒด ID์˜ ์œ ์ผํ•œ ์ •์˜ ๊ธฐ๋Šฅ์€ ๊ธธ์ด๊ฐ€ 12๋ฐ”์ดํŠธ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. mongodb/js-bson#112๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ๊ธธ์ด๊ฐ€ 12์ธ JS ๋ฌธ์ž์—ด์—๋Š” 12๋ฐ”์ดํŠธ์˜ ๋ชจ๋“ˆ๋กœ ์œ ๋‹ˆ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธธ์ด๊ฐ€ 24์ธ 16์ง„์ˆ˜ ๋ฌธ์ž์—ด์„ ํ™•์ธํ•˜๋ ค๋ฉด ๋ฌธ์ž์—ด์ด /^[a-fA-F0-9]{24}$/ ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

"zzzzzzzzzzzz"๋Š” ์œ ํšจํ•œ ObjectId๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Mongo ์…ธ ๋ชฉ๋ก(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์ง„ ๋ฌธ์ž์—ด์ด ์ผ๋ฐ˜์ ์œผ๋กœ ObjectIds๊ฐ€ ํ‘œํ˜„๋˜๋Š” ๋ฐฉ์‹์ด๋ผ๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ด๊ฒƒ์€ ๋‹ค์†Œ ์ง๊ด€์ ์ด์ง€ ์•Š์€ ๊ฒฝ์šฐ์ด์ง€๋งŒ, ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์œผ๋ฉด ์ •๊ทœ์‹ /^[a-fA-F0-9]{24}$/ ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. :)

String์ด ์•„๋‹Œ ObjectId ์ž์ฒด์— ๋Œ€ํ•ด isValid ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์™œ false๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ? ObjectId๊ฐ€ ์œ ํšจํ•œ ObjectId์ด๋ฏ€๋กœ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ ๋ง์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค -- isValid ์— ์ „๋‹ฌ๋˜๋Š” ๊ฐ์ฒด๋ผ๋ฉด .toString() ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@niftylettuce ๋Œ“๊ธ€์€ #3365์—์„œ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์‚ฌ๋žŒ๋“ค์ด ๋ชฝ๊ตฌ์Šค์—์„œ ObjectIds๋ฅผ ์ƒ๊ฐํ•˜๋Š” ๋ฐฉ์‹๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” bson ํŒจํ‚ค์ง€์˜ ObjectId.isValid() ํ•จ์ˆ˜ ๋กœ ์—ฐ๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ 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 ๋‹น์‹ ์€ ๊ทธ๋ ‡๊ฒŒ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค, mongoose๋Š” ID๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ฟผ๋ฆฌ ์•ฝ์†์„ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

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

์•„, ๋‚ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋จธํŽซ์ด์—ˆ๋Š”์ง€! ๋ฌผ๋ก  ๊ฑฐ์ ˆ๋‹นํ•œ ์•ฝ์†์„ ์ฒ˜๋ฆฌํ•˜์‹ญ์‹œ์˜ค ... ์•„์•„, ๋‚ด ๋‘๋‡Œ. ๊ฐ์‚ฌ ํ•ฉ๋‹ˆ๋‹ค @vkarpov15

ํ”„๋ผ๋ฏธ์Šค๊ฐ€ ๋„ˆ๋ฌด ๊ณจ์น˜ ์•„ํ”ˆ ๊ฒฝ์šฐ์—๋„ ์ฝœ๋ฐฑ์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค MyModel.findOne({ _id: 'invalid' }).exec(error => console.error('error', error)); :)

Valeri๊ฐ€ ๋งํ•œ ์œ„์˜ 12๋ฐ”์ดํŠธ์—์„œ ์ด๋ฏธ ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ObjectId.isValid() ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๋ฐฉ๊ธˆ ์ด๊ฒƒ์œผ๋กœ ๊ฝค ์ž˜ ๊ตฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค.
ObjectId.isValid('The Flagship') === true

@atcwells ๋งŒ์•ฝ ๋‹น์‹ ์ด ๊ทธ ๋น„ํŠธ๋ฅผ ํฌํ•จํ•˜๋„๋ก ๋‹น์‹ ์˜ ๋†’์€ ์ฐฌ์„ฑ ์˜๊ฒฌ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•œ ๊ฒƒ์— ๊ธฐ์ดˆํ•˜์—ฌ ์ฒ˜์Œ์— ๊ทธ๊ฒƒ์„ ํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ๊ณ ๋งˆ์›Œํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค: ObjectId.isValid('The Flagship') === true

์žฌ๋ฏธ์žˆ๋Š” ๋ถ€๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋‹ค์Œ ๋ฌธ์žฅ์€ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
mongoose.Types.ObjectId.isValid("๋‚จ์•„ํ”„๋ฆฌ์นด ๊ณตํ™”๊ตญ")

๋‚ด๊ฐ€ (ํ˜„์žฌ) ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์€ promise catch์—์„œ ์˜ค๋ฅ˜ ์œ ํ˜•์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 'ObjectId'์ธ ๊ฒฝ์šฐ 404๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. API/์›น ์„œ๋น„์Šค ์†Œ๋น„์ž์—๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๊ฑฐ๋‚˜ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— 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);
      }
    });

์—…๋ฐ์ดํŠธ:
์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ฐ ๊ฒฝ๋กœ ์ฒ˜๋ฆฌ๊ธฐ์— ์ด๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹ . ์ „์—ญ catch all ์ฒ˜๋ฆฌ๊ธฐ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

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

์Šคํ‚ค๋งˆ์—์„œ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ชจ๋ฒ” ์‚ฌ๋ก€๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์บ์ŠคํŠธ ์˜ค๋ฅ˜ ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

mongoose๊ฐ€ MongoDB๋งŒ ์ฒ˜๋ฆฌํ•  ๋•Œ isValid์— ๋Œ€ํ•ด ์ •๊ทœ์‹ /^[a-fA-F0-9]{24}$/๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋„ˆ๋ฌด ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฌธ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐ ํ•œ ์‹œ๊ฐ„์„ ํ• ์• ํ–ˆ์œผ๋ฉฐ ๊ฒฐ์ฝ” ์•Œ์•„์ฐจ๋ฆฌ์ง€ ๋ชปํ•  ์–ด๋ฆฌ์„์€ ์ผ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด 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์ด๋ฉฐ, ์ด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ๊ธธ์ด๊ฐ€ 0์ธ ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  $or ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— URL ์Šฌ๋Ÿฌ๊ทธ(๋‚ด ๋‹ค๋ฅธ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜)๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์šฐ์•„ํ•œ ์†”๋ฃจ์…˜์€ ์•„๋‹ˆ์ง€๋งŒ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

@victorbadila ๋„ค, ๋งž์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹จ์ง€ ํžŒํŠธ๋ฅผ ์ฃผ์—ˆ๋‹ค. ๋‚ด ์˜๊ฒฌ์„ ํŽธ์ง‘ํ•˜๊ณ  ์‹ค์ œ๋กœ ๋‚ด๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

validator.js ์—๋Š” isMongoId ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

mongoose๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ๋ช‡ ๊ฐ€์ง€ ์ •์  ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

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 ๋“ฑ๊ธ‰