Mongoose hatası nedir? ObjectId'e Cast, "_id" yolunda XXX değeri için başarısız oldu?


122

Bir istek gönderirken /customers/41224d776a326fb40f000001ve bir belge _id 41224d776a326fb40f000001yok, docolan nullve ben bir iade ediyorum 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);
    });
  };

Bununla birlikte, _idMongoose'un "format" olarak beklediği şeyle eşleşmediğinde (sanırım) örneğin GET /customers/foogarip bir hata döndürülür:

CastError: "_id" yolunda "foo" değeri için ObjectId'ye Cast başarısız oldu.

Peki bu hata nedir?

Yanıtlar:


182

Mongoose'un findByIdyöntemi, idparametreyi modelin _idalanının türüne çevirir, böylece eşleşen dokümanı doğru şekilde sorgulayabilir. Bu bir ObjectId'dir ancak "foo"geçerli bir ObjectId değildir, bu nedenle cast başarısız olur.

Bu 41224d776a326fb40f000001dize geçerli bir Nesne Kimliği olduğu için bu gerçekleşmez .

Bunu çözmenin bir yolu, geçerli bir ObjectId findByIdolup olmadığını görmek için aramanızdan önce bir kontrol eklemektir id:

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

4
@Gremo _idMongoose şemanızda kullanmak için yalnızca bir tür seçersiniz . In "bla"durumda size bir tür kullanmak istiyorsunuz Stringyerine varsayılan ObjectIdve şey bir dizeye dökülebilir olarak bu çeki eklemenize gerek olmazdı.
JohnnyHK

2
Anlıyorum ama bu kontrolden kaçınmak istiyorum. Yönteme iletmek için ObjectIdbelirli bir dizeden ( GETistekten) yeni bir tanesini nasıl oluşturabilirim findById?
gremo

@Gremo Yapamazsın. Yalnızca 24 onaltılık karakter dizisinden ObjectIds oluşturabilirsiniz.
JohnnyHK

1
Bu (benzersiz) kimliğe sahip belgeyi sorgulamak için find ({_ id: yourId}, ...) kullanabilirsiniz. Bu ve JohnnyHK'nin şemanıza _id eklemek için cevabı (istediğiniz 'dizgi' türüyle), sorununuz için tam çözümdür.
Steve Hollasch

1
Bu günlerde, 12 karakter dizisi de bir ObjectId'ye dönüştürülebilir. ObjectId("000000000000") --> 303030303030303030303030
Dan Ross

50

ObjectID'yi kontrol etmek için mevcut işlevleri kullanın.

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

15
Herhangi bir 12 baytlık dizgeyi geçerli kabul etme gibi ilginç davranışa sahip olduğundan, bu yöntemi kullanırken dikkatli olun. Böylece, 'your id here'örneğiniz için bile doğru döndürür . github.com/mongodb/js-bson/issues/106
JohnnyHK

( "burada") console.log; let i = yeni firavun faresi.Types.ObjectId (userId.id); console.log ("şimdi burada"); // bu konsol
yazdırmıyor

11

Bu dizeyi olarak ObjectIdmı ayrıştırıyorsun ?

İşte başvurumda yaptığım şey:

ObjectId.fromString( myObjectIdString );

Evet, yapmalısınız, çünkü bir ObjectId türünü sorguluyorsunuz, bu yüzden döküm gerekli.
gustavohenke

1
Deneyin mongoose.Types.ObjectId.
gustavohenke

1
Çalışıyor, ancak "foo" 'yu ​​geçerken "Geçersiz ObjectId" alıyorum. Öyleyse, başarısız olursa, bir dizeden bir ObjectId oluşturmanın amacı nedir?
gremo

MongoDB belgelerine göre, ObjectIds yalnızca 24 onaltılık bayt olmalıdır.
gustavohenke

1
fromStringbir işlev değil
WasiF

8


_İd: String .in şemasını ekliyorum ve sonra çalışmaya başlıyor


bir yıl sonra bu, connect-mongo ile kullanırken beni kurtardı
Ren44

15 saat kesintisiz çalıştıktan sonra küçük bir noktada takılıp kaldınız.
Kara Mamba

8

Rotalarımı, rota parametrelerini yakalayan diğer rotaların üzerine taşımak zorunda kaldım:

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

İşte buydu. Keşke cevabını bir saat önce bulsaydım. Şerefe!
Sodbileg Gansukh

Bu benim için çalıştı. Bu hatanın arkasındaki nedeni merak ediyorum. Rotanın normal rotaların altına taşınmasının hatanın nasıl ortadan kalkmasına neden olduğunu açıklar mısınız?
Vishwak

Bu benim de çalıştı. Görünüşe göre / test / create bunu / test /: id'yi id = create ile tatmin ediyor. ve string, to_id'ye dönüştürülemez.
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"});
        }

en iyisi geçerliliği kontrol etmektir


3

Benim durumumda, _id: ObjectŞemama eklemek zorunda kaldım ve sonra her şey yolunda gitti.


2

Ayrıca ObjectId.isValid'i aşağıdaki gibi kullanabilirsiniz:

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

1
Referans Hatası: ObjectId tanımlanmadı
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'nin sorusunu sağlayan başka cevaplar da var ve bunlar yıllar önce yayınlandı. Bir yanıt gönderirken, lütfen özellikle eski soruları yanıtlarken yeni bir çözüm veya çok daha iyi bir açıklama eklediğinizden emin olun. Yalnızca kod yanıtları düşük kaliteli olarak kabul edilir: Kodunuzun ne yaptığını ve sorunu nasıl çözdüğünü açıkladığınızdan emin olun.
help-info.de

2

Yakın zamanda benzer bir şeyle karşılaştım ve Mongoose ObjectId hatası olup olmadığını öğrenmek için hatayı yakalayarak çözdüm.

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

Bir doğrulama yöntemi olarak ObjectId dökümünün başarısızlığından yararlanmak için orijinal kodun etrafına sarılmış bir deneme yakalamasında cast ObjectId uygulayarak @gustavohenke çözümünün bir uyarlamasına gittim .

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
Bunu kullanmak güzel olurdu, ancak fromString () artık mevcut değil: github.com/Automattic/mongoose/issues/1890
Brent Washburne

1

Bu eski bir sorudur, ancak istek parametrelerini kontrol etmek için ekspres doğrulayıcı paketi de kullanabilirsiniz.

ekspres doğrulayıcı sürüm 4 (en son):

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

});

ekspres doğrulayıcı sürüm 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')Sorgunuzdaki koşullar için her zaman kullanın , sorgunuzu çalıştırmadan önce kimlik alanını doğrular, sonuç olarak uygulamanız çökmez.



0

Bu sorunu çözmemin yolu kimliği bir dizeye dönüştürmek

backtick ile hoşuma gidiyor: `${id}`

bu sorunu ek yük olmadan çözmelidir


0

ObjectId aşağıdaki şeylerden oluşur.

  1. Unix döneminden bu yana geçen saniyeleri temsil eden 4 baytlık bir değer
  2. 5 baytlık rastgele bir değer (Makine Kimliği 3 bayt ve İşlemci kimliği 2 bayt)
  3. rastgele bir değerle başlayan 3 baytlık bir sayaç.

ObjectId'nin geçerli olup olmadığını doğrulamanın doğru yolu, ObjectId sınıfının kendisinden statik yöntem kullanmaktır.

mongoose.Types.ObjectId.isValid (sample_object_id)


0

Dizeyi ObjectId'ye çevir

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

Nesne Kimliği Hatasını Algılama ve Düzeltme Firavun

faresi kullanarak bir öğeyi silmeye çalışırken bu soruna rastladım ve aynı hatayı aldım. Dönüş dizesine baktıktan sonra, döndürülen dizede benim için hataya neden olan bazı fazladan boşluklar olduğunu gördüm. Bu yüzden, hatalı kimliği tespit etmek için burada verilen cevaplardan birkaçını uyguladım ve ardından fazladan boşlukları dizeden kaldırdım. İşte sorunu nihayet çözmek için benim için çalışan kod.

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

Bu benim için çalıştı ve diğer öğelerin dönüş dizesinde görünmeye başlaması durumunda benzer şekilde kaldırılabileceklerini varsayıyorum.

Umarım bu yardımcı olur.


0

Rotaların sırasını değiştirerek bu sorunu çözdüm.


Bu bir cevap gibi görünmüyor. En iyi ihtimalle bu bir yorumdur.
MS

Bu benim için çalıştı, bloglar için 2 yolum vardı: '/ blogs / create' ve 'blogs /: id'. Ve ikincisi, güzergah sırasına göre ilk sırada geldi. Bu yüzden '/ blogs / create' sayfasına gittiğimde firavun faresi kimlik olarak 'oluştur'u aldı
Wyrone

0

Bununla ilgili sorunlar yaşıyordum ve yapmadan mongoose.ObjectId(id)düzeliyordumTypes

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.