Mongoose cast error

MongooseError constructor. MongooseError is the base class for all Mongoose-specific errors.
  • Error()
  • Error.CastError
  • Error.DivergentArrayError
  • Error.DocumentNotFoundError
  • Error.MissingSchemaError
  • Error.MongooseServerSelectionError
  • Error.OverwriteModelError
  • Error.ParallelSaveError
  • Error.StrictModeError
  • Error.ValidationError
  • Error.ValidatorError
  • Error.VersionError
  • Error.messages
  • Error.prototype.name

Error()

Parameters:
  • msg
    «String» Error message
Type:
  • «constructor»
Inherits:
  • «Error»

MongooseError constructor. MongooseError is the base class for all
Mongoose-specific errors.

Example:

const Model = mongoose.model('Test', new mongoose.Schema({ answer: Number }));
const doc = new Model({ answer: 'not a number' });
const err = doc.validateSync();

err instanceof mongoose.Error.ValidationError; // true


Error.CastError

Type:
  • «property»

An instance of this error class will be returned when mongoose failed to
cast a value.


Error.DivergentArrayError

Type:
  • «property»

An instance of this error will be returned if you used an array projection
and then modified the array in an unsafe way.


Error.DocumentNotFoundError

Type:
  • «property»

An instance of this error class will be returned when save() fails
because the underlying
document was not found. The constructor takes one parameter, the
conditions that mongoose passed to update() when trying to update
the document.


Error.MissingSchemaError

Type:
  • «property»

Thrown when you try to access a model that has not been registered yet


Error.MongooseServerSelectionError

Type:
  • «property»

Thrown when the MongoDB Node driver can’t connect to a valid server
to send an operation to.


Error.OverwriteModelError

Type:
  • «property»

Error.ParallelSaveError

Type:
  • «property»

An instance of this error class will be returned when you call save() multiple
times on the same document in parallel. See the FAQ for more
information.


Error.StrictModeError

Type:
  • «property»

Thrown when your try to pass values to model contrtuctor that
were not specified in schema or change immutable properties when
strict mode is "throw"


Error.ValidationError

Type:
  • «property»

An instance of this error class will be returned when validation failed.
The errors property contains an object whose keys are the paths that failed and whose values are
instances of CastError or ValidationError.


Error.ValidatorError

Type:
  • «property»

A ValidationError has a hash of errors that contain individual
ValidatorError instances.

Example:

const schema = Schema({ name: { type: String, required: true } });
const Model = mongoose.model('Test', schema);
const doc = new Model({});

// Top-level error is a ValidationError, **not** a ValidatorError
const err = doc.validateSync();
err instanceof mongoose.Error.ValidationError; // true

// A ValidationError `err` has 0 or more ValidatorErrors keyed by the
// path in the `err.errors` property.
err.errors['name'] instanceof mongoose.Error.ValidatorError;

err.errors['name'].kind; // 'required'
err.errors['name'].path; // 'name'
err.errors['name'].value; // undefined

Instances of ValidatorError have the following properties:

  • kind: The validator’s type, like 'required' or 'regexp'
  • path: The path that failed validation
  • value: The value that failed validation

Error.VersionError

Type:
  • «property»

An instance of this error class will be returned when you call save() after
the document in the database was changed in a potentially unsafe way. See
the versionKey option for more information.


Error.messages

Type:
  • «property»
See:
  • Error.messages

The default built-in validator error messages.


Error.prototype.name

Type:
  • «String»

The name of the error. The name uniquely identifies this Mongoose error. The
possible values are:

  • MongooseError: general Mongoose error
  • CastError: Mongoose could not convert a value to the type defined in the schema path. May be in a ValidationError class’ errors property.
  • DisconnectedError: This connection timed out in trying to reconnect to MongoDB and will not successfully reconnect to MongoDB unless you explicitly reconnect.
  • DivergentArrayError: You attempted to save() an array that was modified after you loaded it with a $elemMatch or similar projection
  • MissingSchemaError: You tried to access a model with mongoose.model() that was not defined
  • DocumentNotFoundError: The document you tried to save() was not found
  • ValidatorError: error from an individual schema path’s validator
  • ValidationError: error returned from validate() or validateSync(). Contains zero or more ValidatorError instances in .errors property.
  • MissingSchemaError: You called mongoose.Document() without a schema
  • ObjectExpectedError: Thrown when you set a nested path to a non-object value with strict mode set.
  • ObjectParameterError: Thrown when you pass a non-object value to a function which expects an object as a paramter
  • OverwriteModelError: Thrown when you call mongoose.model() to re-define a model that was already defined.
  • ParallelSaveError: Thrown when you call save() on a document when the same document instance is already saving.
  • StrictModeError: Thrown when you set a path that isn’t the schema and strict mode is set to throw.
  • VersionError: Thrown when the document is out of sync

I am new to node.js, so I have a feeling that this will be something silly that I have overlooked, but I haven’t been able to find an answer that fixes my problem. What I’m trying to do is create a path that will create a new child object, add it to the parent’s array of children, then return the child object to the requester. The problem that I am running into is that if I pass the string id into findById, node crashes with

TypeError: Object {} has no method ‘cast’

If I try to pass in an ObjectId instead, I get

CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»

Here is a rough outline of my code:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId; //Have also tried Schema.Types.ObjectId, mongoose.ObjectId

mongoose.connect('mongodb://user:password@server:port/database');

app.get('/myClass/:Id/childClass/create', function(request, result) {
  var id = new ObjectId(request.params.Id);
  MyClass.findById(id).exec( function(err, myClass) {
    if (err || !myClass) { result.send("error: " + err + "<br>" + JSON.stringify(id) || ("object '" + request.params.Id + "' not found: " + id)); return; }
    var child = ChildClass();
    myClass.Children.addToSet(child);
    myClass.save();
    result.send(child);
  });
});

If I execute this code with the path «/myClass/51c35e5ced18cb901d000001/childClass/create», this is the output of the code:

error: CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»
{«path»:»51c35e5ced18cb901d000001″,»instance»:»ObjectID»,»validators»:[],»setters»:[],»getters»:[],»_index»:null}

I’ve tried using findOne and passing in {_id:id} instead, but this appears to be exactly what findById does. I’ve tried the different classes for ObjectId that I’ve seen listed on other sites. I’ve tried calling ObjectId() like a function instead of a constructor and that returns undefined. At this point, I’m running out of ideas and it doesn’t seem that googling for an answer is helping. Any ideas on what I’m doing wrong?

Also, like I said, I’m new to node/Mongo/Mongoose/Express, so if there is a better way to accomplish my goal, please let me know. I appreciate all feedback.

EDIT:

After the workaround from Peter Lyons, I googled another error that I was running into and found findByIdAndUpdate, which works as expected and does exactly what I was hoping to do. I’m still not sure why findById and findOne were giving me such issues and I’m curious to know (maybe a bug report needs to be filed), so I’ll leave this open in case someone else has an answer.

Содержание

  1. Mongoose: Cast to ObjectId failed for value
  2. 2 Answers 2
  3. CastError: Cast to ObjectId failed for value
  4. 2 Answers 2
  5. Mongoose: CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»
  6. 17 Answers 17
  7. Mongoose: CastError: Cast to ObjectId failed for value “me” at path “_id”
  8. 2 Answers 2
  9. Linked
  10. Related
  11. Hot Network Questions
  12. Subscribe to RSS
  13. CastError: Cast to ObjectId failed for value «type: ‘Buffer’»

Mongoose: Cast to ObjectId failed for value

I’m trying to specify the schema of my db in mongoose. At the moment I do this:

I create the schemas and try to save some data.

The db I try to create looks like this: Specify schema in mongoose .

How can I fix this?

2 Answers 2

The example from the mongoose docs you referenced uses Number for the personSchema._id field, and ObjectId for the others.

I presume they do this in the example only to demonstrate that it’s possible to use either. If you do not specify _id in the schema, ObjectId will be the default.

Here, all your records have an _id field which is an ObjectId , yet you’re treating them like numbers. Furthermore, fields like personID and taskID do not exist, unless you’ve left out the part where you define them.

If you did want to use numbers for all your _id fields, you’d have to define that in the schemas.

Then to create a news item with a particular ID, and assign it to a creator:

However the thing to note here is that when you use something other than ObjectId as the _id field, you’re taking on the responsibility of managing these values yourself. ObjectIds are autogenerated and require no extra management.

Edit: I also noticed that you’re storing refs on both sides of your associations. This is totally valid and you may want to do it sometimes, but note that you’d have to take care of storing the references yourself in the pre hook.

Источник

CastError: Cast to ObjectId failed for value

I get mongoose error every time I try to check my if condition (project== null). Please see the code below:

It works fine if I enter the right projected. But I want to handle the case when the specified projectID doesn’t exist. When I enter some random projectID in the URL parameter it is throwing : UnhandledPromiseRejectionWarning: CastError: Cast to ObjectId failed for value «123» at path «_id» for model «Project» .

Any ideas what am I doing wrong?

2 Answers 2

It’s not the issue with the condition project== null , here in this case your query isn’t even getting fired from code to DB.

Issue :

So mongoose .findById() will take in a valid string value & internally convert it to type ObjectId() .

If you pass in a string 5eb78994dbb89024f04a2507 to .findById() then mongoose internally does something like this .findOne(<_id : objectid(‘5eb78994dbb89024f04a2507’)>) .

When I say valid string you need to understand a string value inside an ObjectId() has to be of certain form, Check this : MongoDB-ObjectId.

If you pass in 123 which is not a valid string for ObjectId() mongoose if failing to convert to ObjectId() and throwing that error even prior to forming your query.

So to test your scenario, if your actual string is something like this 5eb78994dbb89024f04a2507 just tweak it with changing last value like 5eb78994dbb89024f04a2508 and give it a try or you can get a sample from above provided link or from another collection’s doc in your DB.

Источник

Mongoose: CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»

I am new to node.js, so I have a feeling that this will be something silly that I have overlooked, but I haven’t been able to find an answer that fixes my problem. What I’m trying to do is create a path that will create a new child object, add it to the parent’s array of children, then return the child object to the requester. The problem that I am running into is that if I pass the string id into findById, node crashes with

TypeError: Object <> has no method ‘cast’

If I try to pass in an ObjectId instead, I get

CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»

Here is a rough outline of my code:

If I execute this code with the path «/myClass/51c35e5ced18cb901d000001/childClass/create», this is the output of the code:

error: CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»

I’ve tried using findOne and passing in <_id:id>instead, but this appears to be exactly what findById does. I’ve tried the different classes for ObjectId that I’ve seen listed on other sites. I’ve tried calling ObjectId() like a function instead of a constructor and that returns undefined. At this point, I’m running out of ideas and it doesn’t seem that googling for an answer is helping. Any ideas on what I’m doing wrong?

Also, like I said, I’m new to node/Mongo/Mongoose/Express, so if there is a better way to accomplish my goal, please let me know. I appreciate all feedback.

EDIT:

After the workaround from Peter Lyons, I googled another error that I was running into and found findByIdAndUpdate, which works as expected and does exactly what I was hoping to do. I’m still not sure why findById and findOne were giving me such issues and I’m curious to know (maybe a bug report needs to be filed), so I’ll leave this open in case someone else has an answer.

17 Answers 17

Short answer: use mongoose.Types.ObjectId.

Mongoose (but not mongo) can accept object Ids as strings and «cast» them properly for you, so just use:

However, the caveat is if req.params.id is not a valid format for a mongo ID string, that will throw an exception which you must catch.

So the main confusing thing to understand is that mongoose.SchemaTypes has stuff you only use when defining mongoose schemas, and mongoose.Types has the stuff you use when creating data objects you want to store in the database or query objects. So mongoose.Types.ObjectId(«51bb793aca2ab77a3200000d») works, will give you an object you can store in the database or use in queries, and will throw an exception if given an invalid ID string.

findOne takes a query object and passes a single model instance to the callback. And findById is literally a wrapper of findOne(<_id: id>) (see source code here). Just find takes a query object and passes an array of matching model instances to the callback.

Just go slow. It’s confusing but I can guarantee you you are getting confused and not hitting bugs in mongoose at this point. It’s a pretty mature library, but it takes some time to get the hang of it.

The other suspect thing I see in your snippet is not using new when instantiating ChildClass . Beyond that, you’ll need to post your schema code in order for us to help you tract down any CastErrors that remain.

Источник

Mongoose: CastError: Cast to ObjectId failed for value “me” at path “_id”

I know there are a lot of version of this question, but I couldn’t find anything helping me.

Here is the error :

I’m adapting some of Yeoman boilerplate auth code and I didn’t touch this part. Any clues would be greatly appreciated.

for completness, here my api for ‘me’

2 Answers 2

You are trying to access a object with findOne by querying _id to be equal to ‘me’. Mongoose is attempt to convert the string ‘me’ to an ObjectId but fails. I can’t tell from the traceback if it’s your me function which is the issue (that’s the only place where findOne is used in the code you have provided), but you could try to change the function call to User.findById(userId, . ) instead. Don’t see why userId is equal to ‘me’ however or if that would help any at all. Hope this gave you some direction at least. Add a comment if you still have problems.

it is old question but since i got the same issue and resolved the issue, I want to post for a future reference.

you get this error because you put

you should always put specific routes before the generic ones.

Linked

Hot Network Questions

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.1.14.43159

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

CastError: Cast to ObjectId failed for value «type: ‘Buffer’»

Tried to create a new user on my web application without realizing there was already a user in my database with the same username. For some reason, this boundary case broke my app and now everytime I try to go to the home page, I get:

(node:14649) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): CastError: Cast to ObjectId failed for value «< type: ‘Buffer’, data: [ 89, 243, 30, 231, 66, 69, 45, 56, 123, 65, 153, 72 ] >» at path «_id» for model «users» (node:14649) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

What makes this question unique from the other questions here on stackoverflow is the fact that the type is ‘Buffer’. None of the other questions had that specific issue. I have no idea how a buffer was created when I am not using them at all in my database or node server.

Here is the duplicate error message that occurred just before the buffer error:

< MongoError: E11000 duplicate key error collection: crud2.users index: username_1 dup key: < : «lightbeam» >at Function.MongoError.create (/Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb-core/lib/error.js:31:11) at toError (/Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/utils.js:139:22) at /Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/collection.js:668:23 at handleCallback (/Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/utils.js:120:56) at /Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/bulk/unordered.js:465:9 at handleCallback (/Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/utils.js:120:56) at resultHandler (/Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb/lib/bulk/unordered.js:413:5) at /Users/*/Desktop/coding/apps/thequoteapp/node_modules/mongodb-core/lib/connection/pool.js:469:18 at _combinedTickCallback (internal/process/next_tick.js:131:7) at process._tickCallback (internal/process/next_tick.js:180:9) name: ‘MongoError’, message: ‘E11000 duplicate key error collection: crud2.users index: username_1 dup key: < : «lightbeam» >‘, driver: true, code: 11000, index: 0, errmsg: ‘E11000 duplicate key error collection: crud2.users index: username_1 dup key: < : «lightbeam» >‘, getOperation: [Function], toJSON: [Function], toString: [Function] >

Here is my user schema:

And here is the get request defined in my route.js file:

And finally the post request to create a new user:

I have tried restarting the nodemon and the mongodb server, and I have tried using:

to clear any and all instances of the mongodb server. Please help!

Источник

When sending a request to /customers/41224d776a326fb40f000001 and a document with _id 41224d776a326fb40f000001 does not exist, doc is null and I’m returning a 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);
    });
  };

However, when _id does not match what Mongoose expects as «format» (I suppose) for example with GET /customers/foo a strange error is returned:

CastError: Cast to ObjectId failed for value «foo» at path «_id».

So what’s this error?

27 Answers

Mongoose’s findById method casts the id parameter to the type of the model’s _id field so that it can properly query for the matching doc. This is an ObjectId but "foo" is not a valid ObjectId so the cast fails.

This doesn’t happen with 41224d776a326fb40f000001 because that string is a valid ObjectId.

One way to resolve this is to add a check prior to your findById call to see if id is a valid ObjectId or not like so:

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

Use existing functions for checking ObjectID.

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

I had to move my routes on top of other routes that are catching the route parameters:

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

Are you parsing that string as ObjectId?

Here in my application, what I do is:

ObjectId.fromString( myObjectIdString );

I have the same issue I add
_id: String .in schema then it start work

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

best is to check validity

In my case, I had to add _id: Object into my Schema, and then everything worked fine.

it happens when you pass an invalid id to mongoose. so first check it before proceeding, using mongoose isValid function

import mongoose from "mongoose";

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

This might be a case of routes mismatch if you have two different routes like this

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

then you have to be careful putting the route that is using a param after the regular route that worked for me

You can also use ObjectId.isValid like the following :

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

I was faced with something similar recently and solved it by catching the error to find out if it’s a Mongoose ObjectId error.

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

You could either validate every ID before using it in your queries (which I think is the best practice),

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

… or you could monkey patch Mongoose to ignore those casting errors and instead use a string representation to carry on the query. Your query will of course not find anything, but that is probably what you want to have happened anyway.

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

If above solutions do not work for you.
Check if you are sending a GET request to a POST route.
It was that simple and stupid for me.

I went with an adaptation of the @gustavohenke solution, implementing cast ObjectId in a try-catch wrapped around the original code to leverage the failure of ObjectId casting as a validation method.

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

This is an old question but you can also use express-validator package to check request params

express-validator version 4 (latest):

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

    });

});

Always use mongoose.Types.ObjectId('your id')for conditions in your query it will validate the id field before running your query as a result your app will not crash.

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

I was having problems with this and fixed doing mongoose.ObjectId(id) without Types

ObjectId is composed of following things.

  1. a 4-byte value representing the seconds since the Unix epoch
  2. a 5-byte random value (Machine ID 3 bytes and Processor id 2 bytes)
  3. a 3-byte counter, starting with a random
    value.

Correct way to validate if the objectId is valid is by using static method from ObjectId class itself.

mongoose.Types.ObjectId.isValid(sample_object_id)

The way i fix this problem is transforming the id into a string

i like it fancy with backtick:
`${id}`

this should fix the problem with no overhead

Cast string to 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

Detecting and Correcting the ObjectID Error

I stumbled into this problem when trying to delete an item using mongoose and got the same error. After looking over the return string, I found there were some extra spaces inside the returned string which caused the error for me. So, I applied a few of the answers provided here to detect the erroneous id then remove the extra spaces from the string. Here is the code that worked for me to finally resolve the issue.

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

This worked for me and I assume if other items start to appear in the return string they can be removed in a similar way.

I hope this helps.

I had the same error, but in a different situation than in the question, but maybe it will be useful to someone.

The problem was adding buckles:

Wrong:

    const gamesArray = [myId];

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

Correct:

    const gamesArray = [myId];

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

In my case the parameter id length was 25, So I trimmed first character of parameter id and tried. It worked.

Blockquote

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

To change the string object to ObjectId instance fromString() method is not exist anymore. There is a new method createFromHexString().

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

I fixed this problem changing the order of the routes.

Чтобы сделать приложение с помощью мангуста и ejs

Я попытался деградировать другую версию мангуста, чтобы уловить проблему. Тоже пытался утешить.регистрируйте проблемы, из которых я узнал, что коллекция списков собирает данные с помощью метода .save (), в то время как коллекция элементов не может быть сохранена. Это происходит после того, как найденный список приложения.post(‘/’ ) выдает значение null, что приводит к ошибке «невозможно нажать значение null». MongooseError [CastError]: Cast to ObjectId failed for value "{ name: 'C' }" at path "_id" for model "List" Эта ошибка возникает после нажатия на флажок . Который должен был удалить элементы внутри коллекции элементов пользовательского URL-адреса. Во время кодирования он работал некоторое время, затем перестал работать из-за некоторых перерывов в коде.

Файл Package.json:

 {
  "name": "todolist-v1",
  "version": "1.0.0",
  "description": "To do list app by EJS, backend API, MongoDB database",
  "main": "app.js",
  "scripts": {
    "test": "echo "Error: no test specified" amp;amp; exit 1",
    "start": "node app.js"
  },
  "author": "Clinto Abraham Ayamkudiyil",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.3",
    "ejs": "^2.6.1",
    "express": "^4.17.1",
    "lodash": "^4.17.21",
    "mongoose": "^5.12.1"
  }
}

 

Обновлена версия npm для мангуста, ошибки в hyper :

 CastError: Cast to ObjectId failed for value "{ name: 'Delete' }" at path "_id" for model "List"
    at model.Query.exec (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:4361:21)
    at model.Query.Query.findOneAndRemove (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:3108:8)
    at Function.Model.findOneAndRemove (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:2909:13)
    at Function.Model.findByIdAndRemove (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:2961:15)
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListapp.js:132:10
    at Layer.handle [as handle_request] (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterlayer.js:95:5)
    at next (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterroute.js:137:13)
    at Route.dispatch (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterroute.js:112:3)
    at Layer.handle [as handle_request] (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterlayer.js:95:5)
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterindex.js:281:22
    at Function.process_params (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterindex.js:335:12)
    at next (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterindex.js:275:10)
    at serveStatic (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesserve-staticindex.js:75:16)
    at Layer.handle [as handle_request] (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterlayer.js:95:5)
    at trim_prefix (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterindex.js:317:13)
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesexpresslibrouterindex.js:284:7 {
  messageFormat: undefined,
  stringValue: `"{ name: 'Delete' }"`,
  kind: 'ObjectId',
  value: { name: 'Delete' },
  path: '_id',
  reason: Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
      at new ObjectID (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesbsonlibbsonobjectid.js:59:11)
      at castObjectId (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibcastobjectid.js:25:12)
      at ObjectId.cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschemaobjectid.js:279:12)
      at ObjectId.SchemaType.applySetters (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschematype.js:1104:12)
      at ObjectId.SchemaType._castForQuery (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschematype.js:1539:15)
      at ObjectId.SchemaType.castForQuery (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschematype.js:1529:15)
      at ObjectId.SchemaType.castForQueryWrapper (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschematype.js:1506:20)
      at cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibcast.js:274:34)
      at model.Query.Query.cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:4801:12)
      at castQuery (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:4601:18)
      at model.Query.Query._findAndModify (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:3461:23)
      at model.Query.<anonymous> (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:3424:8)
      at model.Query._wrappedThunk [as _findOneAndRemove] (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibhelpersquerywrapThunk.js:16:8)
      at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_moduleskareemindex.js:370:33
      at processTicksAndRejections (internal/process/task_queues.js:75:11)
}
 { _id: 6058941ad1f874331c5bd61b, name: '' }  Delete  null

events.js:292
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'push' of null
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListapp.js:99:19
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:4870:16
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:4870:16
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibhelperspromiseOrCallback.js:24:16
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:4893:21
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:4400:11
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_moduleskareemindex.js:136:16
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
Emitted 'error' event on Function instance at:
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibmodel.js:4872:13
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibhelperspromiseOrCallback.js:24:16
    [... lines matching original stack trace ...]
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
 

EJS FILE

  <%- include("header") -%>

  <div class="box" id="heading">
    <h1> <%= listTitle %> </h1>
  </div>

  <div class="box">
    <% newListItems.forEach(function(item){ %>
      <form action="/delete" method="post">
        <div class="item">
          <input 
            type="checkbox" 
            onchange="this.form.submit()" 
            value="<%= item._id %>" 
            name="checkbox"
          >
          <p><%=  item.name  %></p>
        </div>
        <input 
          type='hidden' 
          name="listName"
          value="<%= listTitle %>" 
        >
      </form>
    <% }); %>


      <form 
        class="item" 
        action="/" 
        method="post"
      >
        <input 
          type="text" 
          name="newItem" 
          placeholder="New Item" 
          autocomplete="off"
        >
        <button 
          type="submit" 
          name="list" 
          value=" <%= listTitle %> "
        > </button>
      </form>
  </div>

<%- include("footer") -%>
 

app.js with app.post(‘delete’) has errors initiated

 c//jshint esversion:6

const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const _ = require('lodash');

const { Schema } = mongoose;

const date = require(__dirname   "/date.js");
var today = date.getDate();

const app = express();

app.set('view engine', 'ejs');

app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));

mongoose.connect("mongodb://localhost:27017/todolistDB", {
  useNewUrlParser: true, 
  useUnifiedTopology: true,
  useFindAndModify: true,
  useCreateIndex : true
});  //useNewUrlParser: true is used for avoiding the deprecation warning

const itemsSchema = new Schema({
  name: String 
});

const Item = mongoose.model("Item", itemsSchema);  // Collections name is Items, so we use singular form in model as 'Item'

const item1 = new Item({ name: "Hey, today's do list."});
const item2 = new Item({ name: "Hit the   button to add a new item"});
const item3 = new Item({ name: "<= Hit this checkbox to delete an item."});
const defaultItems = [item1, item2, item3];

// const items = ["Buy Food", "Cook Food", "Eat Food"];
// const workItems = [];

const listSchema = new Schema({
  name: String,
  items: [itemsSchema]
});

const List = mongoose.model('List', listSchema);


app.get("/", function(req, res) {
  Item.find({}, function(err, foundItems){
    console.log(foundItems);
    if (foundItems.length === 0){
      Item.insertMany(defaultItems, function(err){
        if (err){
          console.log(err);
        } else {
          console.log("Successfully saved the default items to DB.");  
        } 
        res.redirect("/");
      });
    } else{
      console.log(today);
      res.render("list", 
        {
          listTitle: today, 
          newListItems: foundItems
        }
      );
    }
  });
});

app.post("/", function(req, res){
  const itemName = req.body.newItem;
  const item = new Item( { name: itemName } );
  const listName = req.body.list;
  // console.log(itemName, item, listName);

  if (listName === today){
    item.save(function (err) {
      if (err) {
        console.log(err);
        return handleError(err);
      } else {
        console.log('successfully saved inside "/" route content under todays date');
      }
    });
    res.redirect("/");
    console.log( itemName, item, listName); 
    //test add { _id: 6058562ddb96b030fcddc85e, name: 'test add' }  Clintoayamkudi  
  } else {
     List.findOne({name : listName }, function(err, foundList){

      if (err){
        console.log(err, itemName, item, listName);
      } else { 
        console.log( itemName, item, listName, foundList);
        //test add { _id: 6058562ddb96b030fcddc85e, name: 'test add' }  Clintoayamkudi  null
        foundList.push(item);
        // foundList.markModified('items');           // basically it helps in saving the modified files , since items is not readable -not helpful.
        foundList.save();
        res.redirect('/'   listName);
      }
    });

  }
  // if (req.body.list === "Work") {
  //   workItems.push(item);
  //   res.redirect("/work");
  // } else {
  //   items.push(item);
  //   res.redirect("/");
  // }

});

app.post("/delete", function(req, res){
  const checkedItemId = req.body.checkbox;
  const listName = req.body.listName;
  console.log(checkedItemId, req.body, listName);
  //605315035dbba527c004e58e { checkbox: '605315035dbba527c004e58e', listName: 'Monday, March 22' } Monday, March 22
  if(listName === today){
    Item.findByIdAndRemove(checkedItemId, function(err){
      if(!err){
        console.log("successfully removed the checked item from the item list!!!");
        res.redirect("/");
      } 
    });
  } else {
    console.log(checkedItemId, listName);
    //605878c7707cee19145c7779 Clinto92
    List.findByIdAndRemove(
      {
        name: listName
      }, 
      {
        $pull : {
                  _id : checkedItemId
                }
      }, 
    function(err){
      if(!err){
        res.redirect('/'   listName);
      } else {
        console.log(err);
      }
    });
  }
  
});


app.get("/:customListName", function(req,res){
  const customListName = _.capitalize(req.params.customListName);

  List.findOne({name : customListName}, function(err, foundList){
    if(!err){
      if (!foundList){
        console.log("data doesn't exist");
        // create new list
        const list = new List({
          name: customListName,
          items: defaultItems
        }); 
        list.save();
        res.redirect('/'   customListName);
      } else {
        console.log('the searched data exist in the mongoDB');
        // show the existing list
        res.render('list', {
          listTitle: foundList.name, 
          newListItems: foundList.items
        });
      }
    } else {
      console.log(err);
    }
  });  
});


app.get("/:customListName/about", function(req, res){
  res.render("about");
});

app.listen(3000, function() {
  console.log("Server started on port 3000");
});
 

Ошибки в гипертерминале

Я ухудшил версию мангуста, чтобы npm install mongoose@4.7.2 лучше понять, со всеми параметрами, показанными в журнале ниже:

 MongooseError [CastError]: Cast to ObjectId failed for value "{ name: 'C' }" at path "_id" for model "List"
    at new CastError (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooseliberrorcast.js:26:11)
    at ObjectId.cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschemaobjectid.js:147:13)
    at ObjectId.castForQuery (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibschemaobjectid.js:187:15)
    at cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibcast.js:192:34)
    at model.Query.Query.cast (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:2742:12)
    at castQuery (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:2648:18)
    at model.Query.Query._findAndModify (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:1857:17)
    at model.Query.Query.findOneAndRemove (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmquerylibmquery.js:2272:15)
    at model.Query.Query._findOneAndRemove (E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_modulesmongooselibquery.js:1832:31)
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_moduleskareemindex.js:239:8
    at E:Full-Stack-DeveloperEJSputting all togethertoDoListnode_moduleskareemindex.js:18:7
    at processTicksAndRejections (internal/process/task_queues.js:75:11) {
  stringValue: `"{ name: 'C' }"`,
  kind: 'ObjectId',
  value: { name: 'C' },
  path: '_id',
  reason: undefined,
  model: [Function: model] {
    hooks: Kareem { _pres: {}, _posts: {} },
    base: Mongoose {
      connections: [Array],
      plugins: [],
      models: [Object],
      modelSchemas: [Object],
      options: [Object]
    },
    modelName: 'List',
    model: [Function: model],
    db: NativeConnection {
      base: [Mongoose],
      collections: [Object],
      models: [Object],
      config: [Object],
      replica: false,
      hosts: null,
      host: 'localhost',
      port: 27017,
      user: undefined,
      pass: undefined,
      name: 'todolistDB',
      options: [Object],
      otherDbs: [],
      _readyState: 1,
      _closeCalled: false,
      _hasOpened: true,
      _listening: false,
      db: [Db]
    },
    discriminators: undefined,
    schema: Schema {
      obj: [Object],
      paths: [Object],
      subpaths: {},
      virtuals: [Object],
      singleNestedPaths: {},
      nested: {},
      inherits: {},
      callQueue: [Array],
      _indexes: [],
      methods: {},
      statics: {},
      tree: [Object],
      _requiredpaths: [],
      discriminatorMapping: undefined,
      _indexedpaths: undefined,
      query: {},
      childSchemas: [Array],
      s: [Object],
      options: [Object],
      '$globalPluginsApplied': true
    },
    collection: NativeCollection {
      collection: [Collection],
      opts: [Object],
      name: 'lists',
      collectionName: 'lists',
      conn: [NativeConnection],
      queue: [],
      buffer: false,
      emitter: [EventEmitter]
    },
    Query: [Function (anonymous)] { base: [Object] },
    '$__insertMany': [Function (anonymous)],
    insertMany: [Function (anonymous)]
  }
 

Заранее благодарю вас!

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Labels

enhancement

This issue is a user-facing general improvement that doesn’t fix a bug or add a new feature

Comments

@franky-continu

Current behavior is that if I have a schema with an array of object ids referenced to another collection:

privacy: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    index: true,
    required: true
   // removed this line from a comment below...// default: []
  }],

And I want to filter all content for my categories and the public ones, in our case content that does not have a privacy_category setting. i.e. an empty array []

We currently query that with an or query

{"$or":[
   {"privacy": {"$size": 0}},
   {"privacy": {"$in":["5745bdd4b896d4f4367558b4","5745bd9bb896d4f4367558b2"]}}
]}

I would love to query it by only providing an empty array [] as one the comparison options in the $in
statement. Like this, which mlab has confirm is possible in mongodb

"privacy_locations":{
   "$in": ["5745bdd4b896d4f4367558b4","5745bd9bb896d4f4367558b2",[]]
}

(edited later: forgot to mentioned that this query, works from the console without using mongoose)

This throw cast error

{"message":"Error in retrieving records from db.","error":{"message":"Cast to ObjectId failed for value "[]" at path "privacy_locations" for model "Article"","name":"CastError","stringValue":""[]"","kind":"ObjectId","value":[],"path":"privacy_locations"}}

That way I can avoid the $or query statement of an empty array size: 0 and the options in the $in statement and just have one in statement.

If there is a better way, I’m open to change that as well.

I just need to say, give me the content that match these privacy settings (A, B, C) and also give me the content that does not have any privacy settings.

(mongoose version 4.13.2)

@JasonCust

Quoting from the referenced contributing guidelines when creating a new issue:

If you have a question about Mongoose (not a bug report) please post it to either StackOverflow, or on Gitter

You are more likely to get a response much sooner on either of those while not adding to a backlog of bugs/features that the maintainers need to sift through here.

@franky-continu

forgot to mentioned that this query, works from the console without using mongoose
but throws this error in mongoose:

{"message":"Error in retrieving records from db.","error":{"message":"Cast to ObjectId failed for value "[]" at path "privacy_locations" for model "Article"","name":"CastError","stringValue":""[]"","kind":"ObjectId","value":[],"path":"privacy_locations"}}

@franky-continu

It is a bug report. $in [stringid_tobecasted, stringid_tobecasted, []] should cast object ids out of all the strings but not the [] (empty array)

@JasonCust

It’s not a bug. You are attempting to set a default for a field with type ObjectId to an empty array which will fail casting to an ObjectId as correctly reported.

This should be a question on SO or similar about how to properly set a default for an array field.

@franky-continu

Is not because of the default. I added that later. And it is the schema definition.

Given sample data:

db.emptyarray.insert({a:1})
db.emptyarray.insert({a:2, b:null})
db.emptyarray.insert({a:2, b:[]})
db.emptyarray.insert({a:3, b:["perm1"]})
db.emptyarray.insert({a:3, b:["perm1", "perm2"]})
db.emptyarray.insert({a:3, b:["perm1", "perm2", []]})
> db.emptyarray.find({b:[]})
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce0"), "a" : 2, "b" : [ ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce3"), "a" : 3, "b" : [ "perm1", "perm2", [ ] ] }
> db.emptyarray.find({b:{$in:[]}})
> db.emptyarray.find({b:{$in:[[], "perm1"]}})
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce0"), "a" : 2, "b" : [ ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce1"), "a" : 3, "b" : [ "perm1" ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce2"), "a" : 3, "b" : [ "perm1", "perm2" ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce3"), "a" : 3, "b" : [ "perm1", "perm2", [ ] ] }
> db.emptyarray.find({b:{$in:[[], "perm1", null]}})
{ "_id" : ObjectId("5a305f3dd89e8a887e629cde"), "a" : 1 }
{ "_id" : ObjectId("5a305f3dd89e8a887e629cdf"), "a" : 2, "b" : null }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce0"), "a" : 2, "b" : [ ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce1"), "a" : 3, "b" : [ "perm1" ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce2"), "a" : 3, "b" : [ "perm1", "perm2" ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce3"), "a" : 3, "b" : [ "perm1", "perm2", [ ] ] }
> db.emptyarray.find({b:{$in:[[]]}})
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce0"), "a" : 2, "b" : [ ] }
{ "_id" : ObjectId("5a305f3dd89e8a887e629ce3"), "a" : 3, "b" : [ "perm1", "perm2", [ ] ] }

@JasonCust

@franky-continu If you want to continue this conversation then post on SO and I will be happy to explain there why this is NOT a bug but an issue with your default definition.

@franky-continu

Never mind, I need a solution or a way to make it work, not a reason why is not a specific category of not working.

In the end is not working. it would be very easy to include NULL and [] emtpy arrays in the list of fields that can be added to ANY comparison for the $in statement.

Specially given that is the behavior of the $in statement which is being reduced by this casting issue. Very easy to say Cast x y and z if not null or array, ant that would be the end of it.

Thank you so kindly for all the time and replies, please forgive me if this was not your cup of tea or bug :-)

@JasonCust

👍

The solution is simple enough and stems from an apparent slight misunderstanding. However you choose to proceed is totally up to you but the offer is there if you choose to accept it or not.

@franky-continu

What is it? O great mystery-man. I shall create your query in SO, the only place on earth you may type such a SIMPLE thing, hope is not adding an ALL option :-)

@franky-continu

@sobafuchs

@franky-continu if you want, you can do an $or and the other condition can be { $exists: false }

@vkarpov15

I’m somewhat surprised that mongoose even allows saving a doc where something that should be an array of ObjectIds actually saves if one of the elements is []. Just because the mongo shell allows something doesn’t mean mongoose does, because as a general rule of thumb if you define something to have type ObjectId in mongoose, that means in MongoDB it will either be an ObjectId, null, or undefined. Saving an array where you expect an ObjectId sounds like a bug…

@franky-continu

FIRST:
Is not about SAVING. It’s about QUERYING.

SECOND:

I don’t want to save an [] into an array of ObjectIds.

I want to compare an Empty Array var a = []; to another empty array var b = []; and have them match.

Document A defines field a in Mongoose as being an array of ObjectIds

a [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    index: true,
    required: true,
    default: []
  }]

A.a can be [ObjectId-A, ObjectId-B] or A.a can be [] an empty array.

If I query mongoose/mongo by saying {a: []} it will actually works and bring me all document A instances where a is an empty array.

When in mongo you use $in you can specify that at least one element of a is found in the array supplied to the $in label, or that any of the elements supplied in the $in label are equal to (in this case) a.

That means that in mongo you can compare an element of an array or the element being equals which in turn results in being able to compare arrays that are empty to an empty array found within the elements supplied in the array assigned to the $in label

Again: I don’t want to save, I want to query, compare, match. As you can with $in

@franky-continu

@varunjayaraman of course. That is how it works now. But it is highly inefficient.

If I add a label ALL to categories and create a system by which [] is actually [ObjectId-ALL] and I always query privacy by saying $in ALL, any-other-option it works and works faster.

Again, the $in statement compares if field X is in any of the elements provided to $in.
In the exception that X is an array, it looks for any of its elements but it sould still check NULL or [ ] or even [ObjectId-A, ObjectId-B, [ObjectId-C, ObjectId-D], ObjectId-F].

In the last example for the given array to $in, it should compare A, B, then the Whole Array C-D, then C, then D, then F…

And I believe in Mongoose, because it is (IMHO) prematurely and forcely, casting to OID all arguments sent to statement $in, it fails by casting error, which perhaps should even be a non-error. If I look for all Strings equal to 5 maybe in the context of a query it shouldn’t need to throw an exception. Furthermore, it is the field in the document that I have define as being of a certain type, not the arguments I pass to an $in statement…. And Furthermore [] can be of ANY type, including ‘Category’ (in this case), and so does null, null can be of ANY type, so throwing an exception because you turned null into «null» (String word) and then tried to cast string «null» word into an ObjectId is a bit far fetched as an argument for Type consistency. Neither String word «null» nor string word brackets «[]» were sent to the options of $in.

I sent a primitive value of null and an array both should be able to be compared, and Are able to be compared as I mentioned previously, I can do a query by {a: null} or {a: []} (and mongoose does not cast them to ObjetId before the comparison as it does in $in) but I cannot do {a: {$in: [null, []]}} because it is previously transforming null and [] to string «null» and string
«[]» and then casting them to ObjectId, and that removes a big portion of the functionality of $in by removing the possibility of $in to check whole values and not just elements within them.

@vkarpov15

Ah ok, I see, if I’m reading correctly you’re not looking to store a doc with privacy: [[]], you’re looking to store privacy: [] and query for that. My confusion came from this code:

privacy: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    index: true,
    required: true,
    default: [] // <-- this means each element in the array has a default value of `[]`
  }],

Do this instead:

privacy: {
  type: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    index: true,
    required: true
  }],
  default: [] // <-- this is unnecessary, because arrays always have `[]` by default, but this is an example
},

This $in: [] code isn’t something I’ve seen before, but it is a really neat trick, I think we can support that just for $in.

@franky-continu

Oh I see, I’ll correct that.

It works perfectly in mongo but mongoose pre casts everything in $in to objectid which is arguably correct, except that it doesn’t take into consideration null or empty [].

@vkarpov15

null should cast fine, it’s just the [] that’s a little weird. We’ll investigate implementing this next week, thanks for your patience in communicating this issue 👍

@franky-continu

It should, but it doesn’t. I believe it was my first error, but I pasted only the one with []

@sobafuchs

@vkarpov should we keep this labeled as abug or is it more of an enhancement?

@franky-continu

+1 for being either an enhancement or a bug. Technically speaking it is a wrong implementation of behavior of the $in label (function) but it could be argue that because mongoose purpose includes giving schemas, it shouldn’t work as it does in mongodb.

But, casting $in argument (elments) without flexibility it could go against the flexible nature of mongoose which does give schema and structure but it does so within the flexible nature of a functional language and the objectively smart way it is implemented.

Either enhancement or bug will greatly increase current $in state and capabilities as passing strings, nulls, objectids, and [] empty arrays is possible and would be awesome if it becomes possible.

@vkarpov15

@franky-continu the plan right now is to just allow [] and just for $in because of the syntax you mentioned. No other types.

@varunjayaraman yeah, enhancement is more correct 👍

@vkarpov15
vkarpov15

added

enhancement

This issue is a user-facing general improvement that doesn’t fix a bug or add a new feature

and removed

bug?

needs repro script

Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue

labels

Jan 9, 2018

@franky-continu

100% Agreed, fantastic news

vkarpov15

added a commit
that referenced
this issue

Apr 27, 2018

@vkarpov15

@hirengevariya

// Create Geo Location Schema
const GeoSchema = new mongoose.Schema({
type: {type: String, default: ‘Point’},
coordinates: {type: [Number], index: ‘2dsphere’}
});

// Create Uer Location Schema
const UserLocationSchema = new mongoose.Schema({
name: {type: String},
geometry: GeoSchema,
createdAt: Date,
updatedAt: Date
});

newUserLocation: function (req, res) {

const {name, geometry} = req.body;

// Create user location data
const userLocationData = {
  name,
  geometry
};
console.log('New User Data', userLocationData);

UserModel.create(userLocationData).then((userCreateRes) => {
  res.json({status: true, data: userCreateRes, message: 'User location successfully added'})
}).catch(() => {
  res.json({status: false, message: 'User location data failed!'})
})

},

message:
‘Cast to Embedded failed for value «[72.591760]» at path «geometry»‘,
name: ‘CastError’,
stringValue: ‘»[72.591760]»‘,
kind: ‘Embedded’,
value: ‘[72.591760]’,
path: ‘geometry’,
reason: [MongooseError] } },
_message: ‘userLocation validation failed’,
name: ‘ValidationError’ }

Please give me the solution for this.

@vkarpov15

@hirengevariya it looks like the geometry property on req.body is an array, not an object

vkarpov15

added a commit
that referenced
this issue

May 19, 2019

@vkarpov15

Labels

enhancement

This issue is a user-facing general improvement that doesn’t fix a bug or add a new feature

Понравилась статья? Поделить с друзьями:
  • Mongodb error logs
  • Mongo server selection error
  • Mongo server error bad auth authentication failed
  • Mongo network error
  • Mongo error code 11000