Tried to remove _id from collection but not working. I do not know how to resolve this issue. Need help anyone.
model.js:
const schemmaodel = new mongoose.Schema({
"name": { type: string}
}, { _id: false, versionKey: false });
data.controller.js:
var newModel = require(path.resolve('./models/model.js'))(collectionName);
newModel.create({}, function(err, doc) {
});
_id is like a primary key for the collection. If _id is not specified in the Schema then Mongoose will by default _id of type ObjectId.
As per the mongoose documentation you can disable _id on subdocuments only. So in your case, schemmaodel is considered as parent schema and since you have set { _id: false } option on parent schema while saving it will throw an error related to missing _id
Related
I need to define the mongoose schema for for nested documents which is given below.
Documents:
"Options":[{"Value":["28","30","32","34","36","38","40","42","44","46"],"_id":{"$oid":"5de8427af55716115dd43c8f"},"Name":"Size"},{"Value":["White"],"_id":{"$oid":"5de8427af55716115dd43c8e"},"Name":"Colour"}]
I was declaring like below but its not working.
const Product = new Schema(
{
Options: [{ value: { _id: ObjectId, Name: String } }]
},
{
timestamps: {
createdAt: "createdAt",
updatedAt: "updatedAt"
},
collection: "products"
}
);
Here I need the schema where if i will directly add/update the same document then it will be added.
You need to modify your schema like this :
{
Options: [ new Schema ({ value: [...], _id: Schema.Types.ObjectId, Name: String })]
}
This is the way to create an array of subdocuments with Mongoose. If you don't use the "new Schema" key words, you are actually creating a field with type "Mixed", which needs a different way to handle updates.
You can also omit the _id, it should be added automatically.
You can find more information on subdocument on this page :
https://mongoosejs.com/docs/subdocs.html
...and on mixed type fields : https://mongoosejs.com/docs/schematypes.html#mixed
...which will explain shortly the problem.
{
Options: [ new Schema ({ _id: mongoose.Types.ObjectId(),value: [String], Name: String } })]
}
I'd like to configure an upsert. If _id already exists on my object, it recognizes that and updates the match. If _id doesn't exist, it should insert the new document and generate an _id. I'd expect { _id: obj._id } to work, but that overrides the auto-generation of _id. The document appears with _id: null. Is there a filter that would work for this? Do I need to route to insert/update in-code?
Edit: add query.
collection.updateOne(
{ _id: entity._id },
{ $set: entity },
{ upsert: true }
)
Edit: try delete.
Even when I delete the property, no luck.
const upsertTest = (collection) => {
const entity = { date: new Date() };
console.log(entity);
// { date: 2019-11-19T22:16:00.914Z }
const _id = entity._id;
delete entity._id;
console.log(entity);
// { date: 2019-11-19T22:16:00.914Z }
collection.updateOne(
{ _id: _id },
{ $set: entity },
{ upsert: true }
);
console.log(entity);
// { date: 2019-11-19T22:16:00.914Z }
}
But the new document is this:
screenshot of new document
You have to use $setOnInsert to Insert _id
let ObjectID = require('mongodb').ObjectID;
collection.updateOne(
{ _id: entity._id },
{ $set: entity,$setOnInsert:{_id:new ObjectID()}},
{ upsert: true }
)
As the name suggests it will set the _id on insert
If you are using mongodb then new ObjectID() should work,
If its mongoose then you can use mongoose.Types.ObjectId() to generate new ObjectID
Well I Found your Issue
Changed in version 3.0: When you execute an update() with upsert: true and the query matches no existing document, MongoDB will refuse to insert a new document if the query specifies conditions on the _id field.
So in a nutshell you cannot insert a new doc using upsert:true if your query is using _id, Reference
First of all, the _id property WILL always exist, whether you set it yourself or let it auto-generate. So there's no need to check if it exists.
The syntax for upsert is as follows:
db.collection.update({
_id: 'the id you want to check for' // can put any valid 'find' query here
}, {
$set: {
foo: 'bar',
biz: 'baz'
}
}, {
upsert: true
});
If a document with the given _id exists, it will be updated with the $set object. If it does not exist, a new one will be created with the properties of the $set object. If _id is not specified in the $set object, a new _id value will be auto-generated, or will keep using the existing _id value.
The key here is using $set, rather than putting the object right in there. Using set will merge and replace the properties. Without $set it will replace the entire document, removing any unset properties.
Edit: Now seeing the actual query you made, I would suggest you delete the _id property from the entity before setting it. This will make sure it is left alone.
const _id = entity._id;
delete entity._id;
// now do your query using the new `_id` value for the ID.
From our comments you mentioned you were using the local database. The local database allows _id to be null. Using any other DB should fix your issue.
If the entity._id is null then it will create a doc with _id null, We can solve this issue by adding Types.ObjectId(). If the _id doesn't exist then it will create a new document with the proper _id. otherwise, it will update the existing document.
const { Types } = require("mongoose")
collection.updateOne({ _id: Types.ObjectId(entity._id) },{ $set: entity },{ upsert: true})
If you have subdocument arrays, Mongoose automatically creates ids for each one. Example:
{
_id: "mainId"
subDocArray: [
{
_id: "unwantedId",
field: "value"
},
{
_id: "unwantedId",
field: "value"
}
]
}
Is there a way to tell Mongoose to not create ids for objects within an array?
It's simple, you can define this in the subschema :
var mongoose = require("mongoose");
var subSchema = mongoose.Schema({
// your subschema content
}, { _id : false });
var schema = mongoose.Schema({
// schema content
subSchemaCollection : [subSchema]
});
var model = mongoose.model('tablename', schema);
You can create sub-documents without schema and avoid _id. Just add _id: false to your subdocument declaration.
var schema = new mongoose.Schema({
field1: {
type: String
},
subdocArray: [{
_id: false,
field: { type: String }
}]
});
This will prevent the creation of an _id field in your subdoc.
Tested in Mongoose v5.9.10
Additionally, if you use an object literal syntax for specifying a sub-schema, you may also just add _id: false to supress it.
{
sub: {
property1: String,
property2: String,
_id: false
}
}
I'm using mongoose 4.6.3 and all I had to do was add _id: false in the schema, no need to make a subschema.
{
_id: ObjectId
subDocArray: [
{
_id: false,
field: "String"
}
]
}
You can use either of the one
var subSchema = mongoose.Schema({
//subschema fields
},{ _id : false });
or
var subSchema = mongoose.Schema({
//subschema content
_id : false
});
Check your mongoose version before using the second option
If you want to use a predefined schema (with _id) as subdocument (without _id), you can do as follow in theory :
const sourceSchema = mongoose.Schema({
key : value
})
const subSourceSchema = sourceSchema.clone().set('_id',false);
But that didn't work for me. So I added that :
delete subSourceSchema.paths._id;
Now I can include subSourceSchema in my parent document without _id.
I'm not sure this is the clean way to do it, but it work.
NestJS example for anyone looking for a solution with decorators
#Schema({_id: false})
export class MySubDocument {
#Prop()
id: string;
}
Below is some additional information from the Mongoose Schema Type definitions for id and _id:
/**
* Mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field
* cast to a string, or in the case of ObjectIds, its hexString.
*/
id?: boolean;
/**
* Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema
* constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you
* don't want an _id added to your schema at all, you may disable it using this option.
*/
_id?: boolean;
I try to update an MongoDB data by using this code:
db.medicines.update({"_id":"586a048e34e5c12614a7424a"}, {$set: {amount:'3'}})
but unfortantly the query does not recognize the selector "_id":"586a048e34e5c12614a7424a", even if its exists.
Its succsed when I change the key to another like: name,rate and etc..
there is a special way to use update with _id parameter?
Thanks a head.
_id will be the unique ObjectId that mongodb generates for every document before inserting it. The query dint work because _id is an ObjectId and "586a048e34e5c12614a7424a" is a String. You need to wrap _id with ObjectId().
If you're using mongodb query
db.medicines.update({
"_id": ObjectId("586a048e34e5c12614a7424a")
}, {
$set: {
amount: '3'
}
});
If you are using mongoose. You can use findByIdAndUpdate
db.medicines.findByIdAndUpdate({
"_id": "586a048e34e5c12614a7424a"
}, {
$set: {
amount: '3'
}
});
If you have subdocument arrays, Mongoose automatically creates ids for each one. Example:
{
_id: "mainId"
subDocArray: [
{
_id: "unwantedId",
field: "value"
},
{
_id: "unwantedId",
field: "value"
}
]
}
Is there a way to tell Mongoose to not create ids for objects within an array?
It's simple, you can define this in the subschema :
var mongoose = require("mongoose");
var subSchema = mongoose.Schema({
// your subschema content
}, { _id : false });
var schema = mongoose.Schema({
// schema content
subSchemaCollection : [subSchema]
});
var model = mongoose.model('tablename', schema);
You can create sub-documents without schema and avoid _id. Just add _id: false to your subdocument declaration.
var schema = new mongoose.Schema({
field1: {
type: String
},
subdocArray: [{
_id: false,
field: { type: String }
}]
});
This will prevent the creation of an _id field in your subdoc.
Tested in Mongoose v5.9.10
Additionally, if you use an object literal syntax for specifying a sub-schema, you may also just add _id: false to supress it.
{
sub: {
property1: String,
property2: String,
_id: false
}
}
I'm using mongoose 4.6.3 and all I had to do was add _id: false in the schema, no need to make a subschema.
{
_id: ObjectId
subDocArray: [
{
_id: false,
field: "String"
}
]
}
You can use either of the one
var subSchema = mongoose.Schema({
//subschema fields
},{ _id : false });
or
var subSchema = mongoose.Schema({
//subschema content
_id : false
});
Check your mongoose version before using the second option
If you want to use a predefined schema (with _id) as subdocument (without _id), you can do as follow in theory :
const sourceSchema = mongoose.Schema({
key : value
})
const subSourceSchema = sourceSchema.clone().set('_id',false);
But that didn't work for me. So I added that :
delete subSourceSchema.paths._id;
Now I can include subSourceSchema in my parent document without _id.
I'm not sure this is the clean way to do it, but it work.
NestJS example for anyone looking for a solution with decorators
#Schema({_id: false})
export class MySubDocument {
#Prop()
id: string;
}
Below is some additional information from the Mongoose Schema Type definitions for id and _id:
/**
* Mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field
* cast to a string, or in the case of ObjectIds, its hexString.
*/
id?: boolean;
/**
* Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema
* constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you
* don't want an _id added to your schema at all, you may disable it using this option.
*/
_id?: boolean;