Was ist ein Mungofehler? Die Umwandlung in ObjectId ist für den Wert XXX im Pfad "_id" fehlgeschlagen?

122

Wenn das Senden einer Anfrage an /customers/41224d776a326fb40f000001und ein Dokument mit _id 41224d776a326fb40f000001nicht vorhanden ist, docist nullund ich ein 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);
    });
  };

Wenn _idjedoch nicht das übereinstimmt, was Mongoose als "Format" erwartet (nehme ich an), wird beispielsweise GET /customers/fooein seltsamer Fehler zurückgegeben:

CastError: Die Umwandlung in ObjectId ist für den Wert "foo" im Pfad "_id" fehlgeschlagen.

Was ist dieser Fehler?

Gremo
quelle

Antworten:

182

Die findByIdMethode von Mongoose wandelt den idParameter in den Typ des _idModellfelds um, damit das passende Dokument ordnungsgemäß abgefragt werden kann. Dies ist eine ObjectId, aber "foo"keine gültige ObjectId, sodass die Umwandlung fehlschlägt.

Dies ist nicht der Fall, 41224d776a326fb40f000001da diese Zeichenfolge eine gültige ObjectId ist.

Eine Möglichkeit, dies zu beheben, besteht darin, vor dem findByIdAufruf eine Überprüfung hinzuzufügen, um idfestzustellen, ob es sich um eine gültige ObjectId handelt oder nicht:

if (id.match(/^[0-9a-fA-F]{24}$/)) {
  // Yes, it's a valid ObjectId, proceed with `findById` call.
}
JohnnyHK
quelle
4
@Gremo Sie können nur einen Typ auswählen, der _idin Ihrem Mongoose-Schema verwendet werden soll. In dem "bla"Fall würden Sie einen Typ von Stringanstelle des Standardtyps verwenden ObjectIdund müssten diese Prüfung nicht hinzufügen, da alles in eine Zeichenfolge umgewandelt werden kann.
JohnnyHK
2
Ich verstehe, aber ich möchte diese Überprüfung vermeiden. Wie kann ich ObjectIdaus einer bestimmten Zeichenfolge (aus der GETAnforderung) eine neue erstellen, um sie an die findByIdMethode zu übergeben?
Gremo
@Gremo Du kannst nicht. Sie können ObjectIds nur aus 24 Hex-Zeichenfolgen erstellen.
JohnnyHK
1
Sie können einfach find ({_ id: yourId}, ...) verwenden, um das Dokument mit dieser (eindeutigen) ID abzufragen. Dies und JohnnyHKs Antwort, _id zu Ihrem Schema hinzuzufügen (mit dem gewünschten 'String'-Typ), ist die vollständige Lösung für Ihr Problem.
Steve Hollasch
1
Heutzutage können 12 Zeichenfolgen auch in eine ObjectId umgewandelt werden. ObjectId("000000000000") --> 303030303030303030303030
Dan Ross
49

Verwenden Sie vorhandene Funktionen zum Überprüfen der ObjectID.

var mongoose = require('mongoose');
mongoose.Types.ObjectId.isValid('your id here');
xpepermint
quelle
15
Seien Sie vorsichtig mit dieser Methode, da sie das merkwürdige Verhalten hat, jede 12-Byte-Zeichenfolge als gültig zu behandeln. Für Ihr 'your id here'Beispiel gibt es sogar true zurück . github.com/mongodb/js-bson/issues/106
JohnnyHK
console.log ("hier"); let i = new mongoose.Types.ObjectId (userId.id); console.log ("jetzt hier"); // Diese Konsole
druckt
11

Analysieren Sie diese Zeichenfolge als ObjectId?

Hier in meiner Bewerbung mache ich Folgendes:

ObjectId.fromString( myObjectIdString );
gustavohenke
quelle
Ja, das sollten Sie, da Sie einen ObjectId-Typ abfragen, sodass die Umwandlung benötigt wird.
Gustavohenke
1
Versuchen Sie es mongoose.Types.ObjectId.
Gustavohenke
1
Funktioniert, aber ich bekomme "Invalid ObjectId", wenn ich "foo" übergebe. Was bringt es also, eine ObjectId aus einer Zeichenfolge zu erstellen, wenn dies fehlschlägt?
Gremo
Gemäß den MongoDB-Dokumenten dürfen ObjectIds nur 24 hexadezimale Bytes enthalten.
Gustavohenke
1
fromStringist keine Funktion
WasiF
8

Ich habe das gleiche Problem, das ich
_id: String .in Schema hinzufüge, dann fängt es an zu arbeiten

s.babar
quelle
ein Jahr später rettete mich das bei der Verwendung mit connect-
mongo
Vielen Dank, dass Sie an einem kleinen Punkt stecken geblieben sind, nachdem Sie 15 Stunden lang gearbeitet haben.
Black Mamba
8

Ich musste meine Routen über andere Routen verschieben, die die Routenparameter erfassen:

// 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);
Ryan Dhungel
quelle
Das war's. Ich wünschte, ich hätte Ihre Antwort vor einer Stunde gefunden. Prost!
Sodbileg Gansukh
Das hat bei mir funktioniert. Ich bin gespannt auf den Grund für diesen Fehler. Könnten Sie bitte erklären, wie das Verschieben der Route unter die regulären Routen dazu geführt hat, dass der Fehler behoben wurde?
Vishwak
Das hat auch bei mir funktioniert. Sieht so aus, als ob / test / create diese / test /: id mit id = create erfüllt. und string kann nicht in_id umgewandelt werden.
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"});
        }

Am besten überprüfen Sie die Gültigkeit

Yogesh Agrawal
quelle
3

In meinem Fall musste ich _id: Objectmeinem Schema hinzufügen , und dann funktionierte alles einwandfrei.

Crowdpleasr
quelle
2

Sie können ObjectId.isValid auch wie folgt verwenden:

if (!ObjectId.isValid(userId)) return Error({ status: 422 })
ZEE
quelle
1
ReferenceError: ObjectId ist nicht definiert
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
}
Brajalal Pal
quelle
Es gibt andere Antworten, die die Frage des OP stellen, und sie wurden vor vielen Jahren veröffentlicht. Stellen Sie beim Posten einer Antwort sicher, dass Sie entweder eine neue Lösung oder eine wesentlich bessere Erklärung hinzufügen, insbesondere wenn Sie ältere Fragen beantworten. Nur-Code-Antworten gelten als minderwertig: Stellen Sie sicher, dass Sie erklären, was Ihr Code tut und wie er das Problem löst.
help-info.de
1

Ich habe mich für eine Anpassung der @gustavohenke-Lösung entschieden und Cast ObjectId in einem Try-Catch implementiert, der um den Originalcode gewickelt ist, um den Fehler des ObjectId-Castings als Validierungsmethode zu nutzen.

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);
  }
};
Charney Kaye
quelle
1
Dies wäre schön zu benutzen gewesen, aber fromString () existiert nicht mehr: github.com/Automattic/mongoose/issues/1890
Brent Washburne
1

Dies ist eine alte Frage, aber Sie können auch das Express-Validator-Paket verwenden, um Anforderungsparameter zu überprüfen

Express-Validator Version 4 (neueste Version):

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

    });

});
YouneL
quelle
1

Verwenden mongoose.Types.ObjectId('your id')Sie diese Option immer für Bedingungen in Ihrer Abfrage. Dadurch wird das ID-Feld überprüft, bevor Ihre Abfrage ausgeführt wird. Dadurch stürzt Ihre App nicht ab.

Suman
quelle
1

Ich war kürzlich mit etwas Ähnlichem konfrontiert und habe es gelöst, indem ich den Fehler abgefangen habe, um herauszufinden, ob es sich um einen Mongoose ObjectId-Fehler handelt.

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);
    }
});
Erons
quelle
0

Die Art und Weise, wie ich dieses Problem behebe, besteht darin, die ID in einen String umzuwandeln

Ich mag es schick mit Backtick: `${id}`

Dies sollte das Problem ohne Overhead beheben

AiU
quelle
0

ObjectId besteht aus folgenden Dingen.

  1. Ein 4-Byte-Wert, der die Sekunden seit der Unix-Epoche darstellt
  2. ein 5-Byte-Zufallswert (Maschinen-ID 3 Bytes und Prozessor-ID 2 Bytes)
  3. ein 3-Byte-Zähler, der mit einem zufälligen Wert beginnt.

Die korrekte Methode zum Überprüfen, ob die objectId gültig ist, besteht in der Verwendung der statischen Methode aus der ObjectId-Klasse.

mongoose.Types.ObjectId.isValid (sample_object_id)

Sushil Kadu
quelle
0

Zeichenfolge in ObjectId umwandeln

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

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

Erkennen und Korrigieren des ObjectID-Fehlers

Ich bin auf dieses Problem gestoßen, als ich versucht habe, ein Element mit Mungo zu löschen, und habe denselben Fehler erhalten. Nachdem ich mir die Rückgabezeichenfolge angesehen hatte, stellte ich fest, dass in der zurückgegebenen Zeichenfolge einige zusätzliche Leerzeichen vorhanden waren, die den Fehler für mich verursachten. Daher habe ich einige der hier angegebenen Antworten angewendet, um die fehlerhafte ID zu erkennen und dann die zusätzlichen Leerzeichen aus der Zeichenfolge zu entfernen. Hier ist der Code, der für mich funktioniert hat, um das Problem endgültig zu beheben.

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

Dies hat bei mir funktioniert und ich gehe davon aus, dass andere Elemente, die in der Rückgabezeichenfolge angezeigt werden, auf ähnliche Weise entfernt werden können.

Ich hoffe das hilft.

Jim Bray
quelle
0

Ich habe dieses Problem behoben, indem ich die Reihenfolge der Routen geändert habe.

idionisio
quelle
Dies scheint keine Antwort zu sein. Bestenfalls ist es ein Kommentar.
MS
Das hat bei mir funktioniert, ich hatte 2 Routen für Blogs: '/ Blogs / create' und 'Blogs /: id'. Und letztere standen in der Reihenfolge der Routen an erster Stelle. Als ich zum Mungo '/ blogs / create' ging, nahm Mungo 'create' als ID
Wyrone