web-dev-qa-db-ja.com

パス "_id"の値XXXに対するObjectIdへのキャストに失敗したMongooseエラーとは何ですか?

/customers/41224d776a326fb40f000001にリクエストを送信し、_id41224d776a326fb40f000001を含むドキュメントが存在しない場合、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が、たとえばGET /customers/fooを使用して、Mongooseが「フォーマット」として期待するものと一致しない場合(おそらく)、奇妙なエラーが返されます。

CastError:パス「_id」で値「foo」のObjectIdへのキャストに失敗しました。

それで、このエラーは何ですか?

92
gremo

MongooseのfindByIdメソッドは、idパラメーターをモデルの_idフィールドの型にキャストして、一致するドキュメントを適切に照会できるようにします。これはObjectIdですが、"foo"は有効なObjectIdではないため、キャストは失敗します。

この文字列は有効なObjectIdであるため、これは41224d776a326fb40f000001では発生しません。

これを解決する1つの方法は、findById呼び出しの前にチェックを追加して、idが有効なObjectIdであるかどうかを確認することです。

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

ObjectIDを確認するには、既存の関数を使用します。

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

その文字列をObjectIdとして解析していますか?

ここで私のアプリケーションでは、私がやっていることは:

ObjectId.fromString( myObjectIdString );
11
gustavohenke

次のようにObjectId.isValidを使用することもできます。

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

追加したのと同じ問題があります
_ id:String .in schemaその後、作業を​​開始します

2
s.babar

これは古い質問ですが、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
YouneL
//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
}
1
Brajalal Pal
 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"});
        }

妥当性をチェックするのが最善です

1
yogesh agrawal

ルートパラメーターをキャッチしている他のルートの上にルートを移動する必要がありました。

// 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);
0
Ryan Dhungel

この問題を修正する方法は、IDを文字列に変換することです

バックティックが好きです:`${id}`

これはオーバーヘッドなしで問題を解決するはずです

0
AiU

私は@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);
  }
};
0
Charney Kaye

クエリで常にmongoose.Types.ObjectId('your id')条件を使用すると、クエリが実行される前にidフィールドが検証され、アプリがクラッシュしなくなります。

0
Suman

ObjectIdは、次のもので構成されます。

  1. unixエポックからの秒数を表す4バイトの値
  2. 5バイトのランダム値(マシンID 3バイトおよびプロセッサーID 2バイト)
  3. ランダムな値で始まる3バイトのカウンター。

ObjectIdが有効かどうかを検証する正しい方法は、ObjectIdクラス自体の静的メソッドを使用することです。

mongoose.Types.ObjectId.isValid(sample_object_id)

0
Sushil Kadu

または、これを行うことができます

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

ここで述べたように、 $ or条件でのMongooseのfindメソッドは正しく動作しません

0
Madhu Kumar

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
Jim Bray

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
WasiF

誰かがこれに遭遇した場合、私にとってそれを解決したのは、requireの単一引用符から `に変更されたことです。

の代わりに:

const something = require('./models/something');

つかいます:

const something = require(`./models/something`);

面白いように聞こえますが、実際には機能します。

0
Yossi Saadi