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’stype
, like'required'
or'regexp'
path
: The path that failed validationvalue
: 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 errorCastError
: Mongoose could not convert a value to the type defined in the schema path. May be in aValidationError
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 tosave()
an array that was modified after you loaded it with a$elemMatch
or similar projectionMissingSchemaError
: You tried to access a model withmongoose.model()
that was not definedDocumentNotFoundError
: The document you tried tosave()
was not foundValidatorError
: error from an individual schema path’s validatorValidationError
: error returned fromvalidate()
orvalidateSync()
. Contains zero or moreValidatorError
instances in.errors
property.MissingSchemaError
: You calledmongoose.Document()
without a schemaObjectExpectedError
: 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 paramterOverwriteModelError
: Thrown when you callmongoose.model()
to re-define a model that was already defined.ParallelSaveError
: Thrown when you callsave()
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 tothrow
.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.
Содержание
- Mongoose: Cast to ObjectId failed for value
- 2 Answers 2
- CastError: Cast to ObjectId failed for value
- 2 Answers 2
- Mongoose: CastError: Cast to ObjectId failed for value «[object Object]» at path «_id»
- 17 Answers 17
- Mongoose: CastError: Cast to ObjectId failed for value “me” at path “_id”
- 2 Answers 2
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
- 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.
- a 4-byte value representing the seconds since the Unix epoch
- a 5-byte random value (Machine ID 3 bytes and Processor id 2 bytes)
- 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
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)
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.
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"}}
It is a bug report. $in [stringid_tobecasted, stringid_tobecasted, []] should cast object ids out of all the strings but not the [] (empty array)
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.
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", [ ] ] }
@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.
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
👍
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.
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 if you want, you can do an $or and the other condition can be { $exists: false }
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…
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
@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.
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
.
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 [].
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 👍
It should, but it doesn’t. I believe it was my first error, but I pasted only the one with []
@vkarpov should we keep this labeled as abug or is it more of an enhancement?
+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.
@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
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
100% Agreed, fantastic news
vkarpov15
added a commit
that referenced
this issue
Apr 27, 2018
// 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.
@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
Labels
enhancement
This issue is a user-facing general improvement that doesn’t fix a bug or add a new feature