sourcetip

경로 "_id"에서 값 XXX에 대한 Mongoose 오류 ObjectId에 캐스트 실패했습니다.

fileupload 2023. 2. 17. 21:35
반응형

경로 "_id"에서 값 XXX에 대한 Mongoose 오류 ObjectId에 캐스트 실패했습니다.

" " " 에 을 /customers/41224d776a326fb40f000001및 문서가 있습니다._id 41224d776a326fb40f000001하지 않습니다.docnull ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」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는, 「이라고 하는 Mongoose 의 하지 않습니다(제 생각에 「포맷 예를 , 「Mongoose」의 「포맷」과 일치하지 않습니다.GET /customers/foo하다

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

그럼 이 오류는 뭐죠?

구 mong mongfindById가 「」를 합니다.id_id일치하는 문서를 올바르게 쿼리할 수 있도록 합니다.이지만 ObjectId입니다."foo"ObjectId를 선택합니다.

41224d776a326fb40f000001ObjectId를 사용합니다.

하려면 , 「」의 앞에 .findById를 하다id.ObjectId는 ObjectId입니다.

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

기존 함수를 사용하여 개체 확인아이디

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

루트 파라미터를 캐치하고 있는 다른 루트 위에 루트를 이동해야 했습니다.

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

것과 .
.에서 string을 실행한 후: .string을 시작합니다.

이와 같이 2개의 다른 루트가 있는 경우 루트가 일치하지 않을 수 있습니다.

router.route("/order/me") //should come before the route which has been passed with params
router.route("/order/:id")

파라미터를 사용하고 있는 루트를, 나에게 통상의 루트 뒤에 배치하는 것에 주의해 주세요.

은 ""로 ?ObjectId

이 어플리케이션에서 하는 일은 다음과 같습니다.

ObjectId.fromString( myObjectIdString );

mongoose ID합니다.하기 전에 mongoose하여 먼저 진행합니다.isValid

import mongoose from "mongoose";

// add this inside your route
if( !mongoose.Types.ObjectId.isValid(id) ) return false;

', '아까', '아까', '아까'를 붙여야 요._id: Object모든 게 잘 풀렸어요

2019년 11월 19일 기준

하시면 됩니다.isValidObjectId(id)5.7.12mongoose '5.7.12'

https://mongoosejs.com/docs/api/mongoose.html#mongoose_Mongoose-isValidObjectId

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

유효성을 확인하는 것이 최선이다.

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

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

위의 해결 방법이 효과가 없는 경우.POST 루트에 GET 요구를 송신하고 있는지 여부를 체크합니다.
그것은 나에게 그렇게 단순하고 어리석었다.

파라미터 이름 "id"를 "_id"로 변경하기만 하면 됩니다.

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

저는 최근에 비슷한 일을 겪었고, 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);
    }
});

모든 ID를 쿼리에 사용하기 전에 검증할 수도 있습니다(이것이 최선의 방법이라고 생각합니다).

// Assuming you are using Express, this can return 404 automatically.
app.post('/resource/:id([0-9a-f]{24})', function(req, res){
  const id = req.params.id;
  // ...
});

...또는 Mongoose에 패치를 적용하여 이러한 캐스팅 오류를 무시하고 대신 문자열 표현을 사용하여 쿼리를 수행할 수 있습니다.당신의 질문은 물론 아무것도 찾지 못하겠지만, 어쨌든 당신은 그렇게 되길 원할 것입니다.

import { SchemaType }  from 'mongoose';

let patched = false;

export const queryObjectIdCastErrorHandler = {
  install,
};

/**
 * Monkey patches `mongoose.SchemaType.prototype.castForQueryWrapper` to catch
 * ObjectId cast errors and return string instead so that the query can continue
 * the execution. Since failed casts will now use a string instead of ObjectId
 * your queries will not find what they are looking for and may actually find
 * something else if you happen to have a document with this id using string
 * representation. I think this is more or less how MySQL would behave if you
 * queried a document by id and sent a string instead of a number for example.
 */
function install() {
  if (patched) {
    return;
  }

  patch();

  patched = true;
}

function patch() {
  // @ts-ignore using private api.
  const original = SchemaType.prototype.castForQueryWrapper;

  // @ts-ignore using private api.
  SchemaType.prototype.castForQueryWrapper = function () {
    try {
      return original.apply(this, arguments);
    } catch (e) {
      if ((e.message as string).startsWith('Cast to ObjectId failed')) {
        return arguments[0].val;
      }

      throw e;
    }
  };
}

저는 @gustavoenke 솔루션을 채택하여 ObjectId를 원본 코드 주위에 감싼 트라이캐치로 구현하여 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);
  }
};

오래된 질문이지만 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);
    });

});

express-validator 버전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);
        });

    });

});

「」를 사용합니다.mongoose.Types.ObjectId('your id')쿼리의 조건에 대해서는 쿼리를 실행하기 전에 id 필드의 유효성을 확인합니다.그 결과 앱이 크래쉬하지 않습니다.

이로 인해 문제가 이 문제를 했습니다.mongoose.ObjectId(id) 없이Types

ObjectId는 다음과 같은 요소로 구성됩니다.

  1. Unix Epoch 이후의 초수를 나타내는 4바이트 값
  2. 5바이트 랜덤 값(머신 ID 3바이트 및 프로세서 ID 2바이트)
  3. 랜덤 값으로 시작하는 3바이트 카운터

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

mongoose.Types.ObjectId.isValid(sample_object_id)

제 경우 비슷한 루트가 이 문제를 일으켰습니다.

Router.get("/:id", getUserById);
Router.get("/myBookings",getMyBookings);

위의 코드에서는 "/myBookings"를 라우팅하기 위한 get 요구가 있을 때마다 req.params.id이 유효한 ObjectId가 아닌 "myBookings"와 동일한 첫 번째 루트로 이동합니다.

양쪽 루트의 경로를 다르게 함으로써 수정할 수 있습니다.

뭐 이런 거

Router.get("/user/:id", getUserById);
Router.get("/myBookings",getMyBookings);

id 루트 후에 호출한 다음 루트를 id 루트에 연결할 수 없었기 때문에 castError가 발생하고 있습니다.id 루트를 마지막 루트로 선언해야 합니다.

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

에 들어요.`${id}`

오버헤드 없이 문제를 해결할 수 있습니다.

2022년 10월 갱신

를 사용하는 것이 가장 좋습니다.

{id: id} // if you have an id property defined

또는

{_id: new ObjectId(id)} // and search for the default mongodb _id

아니면 이렇게 할 수도 있고

var ObjectId = require('mongoose').Types.ObjectId; var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );

여기에 언급된 바와 같이 $or 조건을 가진 Mongoose의 find 메서드가 제대로 작동하지 않습니다.

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

오류 검출 및 아이디 ★★

를 사용하여 할 때 이했는데, 했습니다.mongoose는 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("/");
      }
    });
});

이것은 나에게 효과가 있었고, 다른 아이템이 반환 문자열에 표시되기 시작하면 같은 방법으로 아이템을 삭제할 수 있을 것입니다.

이게 도움이 됐으면 좋겠어요.

저도 같은 실수를 했지만 질문과는 다른 상황이지만 누군가에게 도움이 될지도 모릅니다.

문제는 버클을 추가하는 것이었습니다.

틀렸다:

    const gamesArray = [myId];

    const player = await Player.findByIdAndUpdate(req.player._id, {
         gamesId: [gamesArray]
    }, { new: true }

정답:

    const gamesArray = [myId];

    const player = await Player.findByIdAndUpdate(req.player._id, {
         gamesId: gamesArray
    }, { new: true }

저의 경우 파라미터 id 길이가 25였기 때문에 파라미터 id의 첫 글자를 트리밍하여 시도하였습니다.됐다.

블록 따옴표

const paramId = req.params.id;
if(paramId.length === 25){
  const _id = paramId.substring(1, 25);
}

문자열 개체를 ObjectId 인스턴스로 변경하는 메서드는 더 이상 존재하지 않습니다.새로운 메서드 createFromHexString()이 추가되었습니다.

const _id = mongoose.Types.ObjectId.fromString(id); // old method not available
const _id = mongoose.Types.ObjectId.createFromHexString(id); // new method.

id 로서 24 문자 미만의 문자열을 송신하는 경우 발생할 수 있습니다.

언급URL : https://stackoverflow.com/questions/14940660/whats-mongoose-error-cast-to-objectid-failed-for-value-xxx-at-path-id

반응형