Mongoose 오류는 무엇입니까? 경로“_id”에서 값 XXX에 대해 ObjectId로 캐스트하지 못했습니다.


122

에 요청 보낼 때 /customers/41224d776a326fb40f000001와있는 문서 _id 41224d776a326fb40f000001가 존재하지 않습니다, doc이다 null와 나는 반환하고 있습니다 404:

  Controller.prototype.show = function(id, res) {
    this.model.findById(id, function(err, doc) {
      if (err) {
        throw err;
      }
      if (!doc) {
        res.send(404);
      }
      return res.send(doc);
    });
  };

그러나 _id몽구스가 "형식"(내 생각에)으로 예상하는 것과 일치하지 않는 경우 예를 들어 GET /customers/foo이상한 오류가 반환됩니다.

CastError : "_id"경로의 "foo"값에 대해 ObjectId로 캐스트하지 못했습니다.

그렇다면이 오류는 무엇입니까?

답변:


182

Mongoose의 findById메서드는 id매개 변수를 모델의 _id필드 유형으로 캐스팅 하여 일치하는 문서를 적절하게 쿼리 할 수 ​​있도록합니다. 이것은 ObjectId이지만 "foo"유효한 ObjectId가 아니므로 캐스트가 실패합니다.

41224d776a326fb40f000001문자열은 유효한 ObjectId이기 때문에 발생하지 않습니다 .

이 문제를 해결하는 한 가지 방법은 findById호출 전에 id유효한 ObjectId인지 여부를 확인하기 위해 확인을 추가하는 것입니다.

if (id.match(/^[0-9a-fA-F]{24}$/)) {
  // Yes, it's a valid ObjectId, proceed with `findById` call.
}

4
@Gremo _idMongoose 스키마에서 사용할 유형을 하나만 선택하면됩니다 . 에서 "bla"경우에 당신은 유형 사용하는 것 String대신에 기본을 ObjectId하고 당신은 아무것도를 문자열로 캐스팅 될 수 있기 때문에이 검사를 추가 할 필요가 없습니다 것입니다.
JohnnyHK

2
이해 합니다만이 수표를 피하고 싶습니다. 메서드 에 전달하기 위해 (요청에서) ObjectId주어진 문자열에서 새 를 만들 수 있습니까? GETfindById
gremo

@ Gremo 당신은 할 수 없습니다. 24 개의 16 진 문자열에서만 ObjectId를 구성 할 수 있습니다.
JohnnyHK 2013

1
find ({_ id : yourId}, ...)를 사용하여 해당 (고유) ID로 문서를 쿼리 할 수 ​​있습니다. 즉, 원하는 '문자열'유형으로 스키마에 _id를 추가하는 JohnnyHK의 답변은 문제에 대한 완전한 솔루션입니다.
Steve Hollasch 2014 년

1
요즘에는 12 개의 문자열을 ObjectId로 캐스트 할 수도 있습니다. ObjectId("000000000000") --> 303030303030303030303030
Dan Ross

50

ObjectID 확인을 위해 기존 함수를 사용합니다.

var mongoose = require('mongoose');
mongoose.Types.ObjectId.isValid('your id here');

15
12 바이트 문자열을 유효한 것으로 취급하는 이상한 동작이 있으므로이 방법을 사용하는 데주의하십시오. 따라서 귀하의 'your id here'예 에서도 true를 반환합니다 . github.com/mongodb/js-bson/issues/106
JohnnyHK

console.log ( "여기"); let i = new mongoose.Types.ObjectId (userId.id); console.log ( "지금 여기"); //이 콘솔도 인쇄되지
인 Yogesh 아그라 왈

11

해당 문자열을 다음과 같이 구문 분석하고 ObjectId있습니까?

여기 내 응용 프로그램에서 내가하는 일은 다음과 같습니다.

ObjectId.fromString( myObjectIdString );

예, ObjectId 유형을 쿼리하므로 캐스트가 필요합니다.
gustavohenke 2013

1
시도해보십시오 mongoose.Types.ObjectId.
gustavohenke 2013

1
작동하지만 "foo"를 전달할 때 "Invalid ObjectId"가 발생합니다. 그렇다면 실패 할 경우 문자열에서 ObjectId를 만드는 요점은 무엇입니까?
gremo

MongoDB 문서에 따라 ObjectId는 24 개의 16 진수 바이트 여야합니다.
gustavohenke 2013

1
fromString함수 아닙니다
WasiF

8


_id : String .in schema를 추가 한 다음 작업을 시작 하는 것과 동일한 문제가 있습니다 .


연결 - 몽고와 함께 사용하는 경우 나중에 년이 저를 저장
Ren44

15 시간 연속 작업 후 작은 지점에 갇혀서 고맙습니다.
Black Mamba

8

경로 매개 변수를 포착하는 다른 경로 위로 경로를 이동해야했습니다.

// require express and express router

const express = require("express");
const router = express.Router();

// move this `/post/like` route on top

router.put("/post/like", requireSignin, like);

// keep the route with route parameter `/:postId` below regular routes

router.get("/post/:postId", singlePost);

그거였다. 한 시간 전에 답변을 찾았 으면 좋겠습니다. 건배!
Sodbileg Gansukh

이것은 나를 위해 일했습니다. 이 오류의 원인이 궁금합니다. 경로를 일반 경로 아래로 이동하면 오류가 어떻게 사라 졌는지 설명해 주시겠습니까?
Vishwak

이것은 나에게도 효과적이었습니다. / test / create가 id = create로이 / test / : id를 충족하는 것처럼 보입니다. 문자열은 to_id로 캐스트 될 수 없습니다.
kaila88

4
 if(mongoose.Types.ObjectId.isValid(userId.id)) {
        User.findById(userId.id,function (err, doc) {
            if(err) {
                reject(err);
            } else if(doc) {
                resolve({success:true,data:doc});
            } else {
                reject({success:false,data:"no data exist for this id"})

            }
        });
        } else {
            reject({success:"false",data:"Please provide correct id"});
        }

가장 좋은 것은 유효성을 확인하는 것입니다


3

제 경우에는 _id: Object스키마 에 추가해야했고 모든 것이 잘 작동했습니다.


2

다음과 같이 ObjectId.isValid를 사용할 수도 있습니다.

if (!ObjectId.isValid(userId)) return Error({ status: 422 })

1
ReferenceError가 : ObjectId가 정의되지 않은
torbenrudgaard

2
//Use following to check if the id is a valid ObjectId?

var valid = mongoose.Types.ObjectId.isValid(req.params.id);
if(valid)
{
  //process your code here
} else {
  //the id is not a valid ObjectId
}

OP의 질문을 제공하는 다른 답변이 있으며 수년 전에 게시되었습니다. 답변을 게시 할 때 특히 이전 질문에 답변 할 때 새로운 솔루션이나 훨씬 더 나은 설명을 추가해야합니다. 코드 전용 답변은 품질이 낮은 것으로 간주됩니다. 코드가 수행하는 작업과 문제를 해결하는 방법에 대한 설명을 제공해야합니다.
help-info.de apr

2

나는 최근에 비슷한 일에 직면했고 오류를 잡아서 Mongoose ObjectId 오류인지 확인하여 해결했습니다.

app.get("/:userId", (req, res, next) => {
    try {
        // query and other code here
    } catch (err) {
        if (err.kind === "ObjectId") {
            return res.status(404).json({
                errors: [
                    {
                        msg: "User not found",
                        status: "404",
                    },
                ],
            });
        }
        next(err);
    }
});


1

@gustavohenke 솔루션을 수정하여 ObjectId 캐스팅의 실패를 유효성 검사 방법으로 활용하기 위해 원본 코드감싸는 try-catch에서 캐스팅 ObjectId를 구현했습니다 .

Controller.prototype.show = function(id, res) {
  try {
    var _id = mongoose.Types.ObjectId.fromString(id);



    // the original code stays the same, with _id instead of id:

    this.model.findById(_id, function(err, doc) {
      if (err) {
        throw err;
      }
      if (!doc) {
        res.send(404);
      }
      return res.send(doc);
    });



  } catch (err) {
    res.json(404, err);
  }
};

1
이것은 사용하기 좋았을 텐데 fromString ()은 더 이상 존재하지 않습니다 : github.com/Automattic/mongoose/issues/1890
Brent Washburne

1

이것은 오래된 질문이지만 express-validator 패키지를 사용하여 요청 매개 변수를 확인할 수도 있습니다.

Express-Validator 버전 4 (최신) :

validator = require('express-validator/check');

app.get('/show/:id', [

    validator.param('id').isMongoId().trim()

], function(req, res) {

    // validation result
    var errors = validator.validationResult(req);

    // check if there are errors
    if ( !errors.isEmpty() ) {
        return res.send('404');
    }

    // else 
    model.findById(req.params.id, function(err, doc) { 
        return res.send(doc);
    });

});

익스프레스 유효성 검사기 버전 3 :

var expressValidator = require('express-validator');
app.use(expressValidator(middlewareOptions));

app.get('/show/:id', function(req, res, next) {

    req.checkParams('id').isMongoId();

    // validation result
    req.getValidationResult().then(function(result) {

        // check if there are errors
        if ( !result.isEmpty() ) {
            return res.send('404');
        }

        // else
        model.findById(req.params.id, function(err, doc) {
            return res.send(doc);
        });

    });

});

1

mongoose.Types.ObjectId('your id')쿼리의 조건에 항상 사용 하면 쿼리를 실행하기 전에 id 필드의 유효성을 검사하므로 앱이 충돌하지 않습니다.



0

이 문제를 해결하는 방법은 ID를 문자열로 변환하는 것입니다.

나는 backtick로 멋지게 좋아합니다. `${id}`

오버 헤드없이 문제를 해결해야합니다.


0

ObjectId는 다음과 같이 구성됩니다.

  1. Unix 시대 이후 초를 나타내는 4 바이트 값
  2. 5 바이트 임의 값 (컴퓨터 ID 3 바이트 및 프로세서 ID 2 바이트)
  3. 임의의 값으로 시작하는 3 바이트 카운터.

objectId가 유효한지 확인하는 올바른 방법은 ObjectId 클래스 자체의 정적 메서드를 사용하는 것입니다.

mongoose.Types.ObjectId.isValid (sample_object_id)


0

문자열을 ObjectId로 캐스트

import mongoose from "mongoose"; // ES6 or above
const mongoose = require('mongoose'); // ES5 or below

let userid = _id
console.log(mongoose.Types.ObjectId(userid)) //5c516fae4e6a1c1cfce18d77

0

ObjectID 오류 감지 및 수정

mongoose를 사용하여 항목을 삭제하려고 할 때이 문제가 발생하고 동일한 오류가 발생했습니다. 반환 문자열을 살펴본 후 반환 된 문자열 내부에 추가 공백이있어 오류가 발생했습니다. 그래서 여기에 제공된 몇 가지 답변을 적용하여 잘못된 ID를 감지 한 다음 문자열에서 추가 공백을 제거했습니다. 마지막으로 문제를 해결하는 데 도움이 된 코드는 다음과 같습니다.

const mongoose = require("mongoose");
mongoose.set('useFindAndModify', false);  //was set due to DeprecationWarning: Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the `useFindAndModify`



app.post("/delete", function(req, res){
  let checkedItem = req.body.deleteItem;
  if (!mongoose.Types.ObjectId.isValid(checkedItem)) {
    checkedItem = checkedItem.replace(/\s/g, '');
  }

  Item.findByIdAndRemove(checkedItem, function(err) {
    if (!err) {
      console.log("Successfully Deleted " + checkedItem);
        res.redirect("/");
      }
    });
});

이것은 나를 위해 일했으며 다른 항목이 반환 문자열에 나타나기 시작하면 비슷한 방법으로 제거 할 수 있다고 가정합니다.

이게 도움이 되길 바란다.


0

이 문제를 해결하여 경로 순서를 변경했습니다.


이것은 대답이 아닌 것 같습니다. 기껏해야 댓글입니다.
MS

이것은 나를 위해 일했으며 블로그에는 '/ blogs / create'와 'blogs / : id'라는 두 가지 경로가 있습니다. 그리고 후자는 경로 순서로 먼저 나왔습니다. 그래서 내가 '/ blogs / create'에 갔을 때 몽구스는 'create'를 id로 취했습니다
Wyrone
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.