eg.
created: {
type: Date,
default: Date.now,
}
, but in mongodb there exists some old data without "created" field. How can I get real data but not Date.now.
We can use $exists here to fetch the new documents which will have the created field.
Mongo Shell Query
db.collection.find( { created: { $exists: true} } )
Related
I'm using Mongoose timestamps in my schema:
{ timestamps: true }
but then when I use $set on my document like so:
$set: {
"person.name": "Owen",
},
The timestamps (createdAt & updatedAt) aren't set or updated.
but when I use $set like so:
$set: {
person: {
name: "Owen"
}
}
then it does work.
Is this the expected behaviour? And is there anything I can do about it?
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})
I have a below aggregate query and I wanted to insert/update this result into another collection.
db.coll1.aggregate([
{
$group:
{
_id: "$collId",
name: {$first:"$name"} ,
type: {$first:"$Type"} ,
startDate: {$first:"$startDate"} ,
endDate: {$first:"$endDate"}
}
}
])
I have another collection coll2, which has fields in the above query and some additional fields too.
I may already have the document created in Coll2 matching the _id:collId in the above query. If this Id matches, I want to update the document with the field values of the result and keep the values of other fields in the document.
If the Id does not exists, it should just create a new document in Coll2.
Is there a way to do it in the MongoDB query. I want to implement this in my Spring application.
We can use $merge to do that. It's supported from Mongo v4.2
db.collection.aggregate([
{
$group:{
"_id":"$collId",
"name": {
$first:"$name"
},
"type":{
$first:"$Type"
},
"startDate":{
$first:"$startDate"
},
"endDate":{
$first:"$endDate"
}
}
},
{
$merge:{
"into":"collection2",
"on":"_id",
"whenMatched":"replace",
"whenNotMatched":"insert"
}
}
])
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'
}
});
I'm working on an app based on mongodb and mongoose. One of my schemas has the following form:
var schema = new mongoose.Schema(
{
name: { type: String },
timestamp: { type: Number, default: Date.now },
// further properties
});
schema.index({ name: 1, timestamp: -1 });
I'd like to retrieve the newest object (i.e., largest timestamp) for a set of name-strings.
E.g., consider the set of names ['a','b']. How do I query the database such that I get returned a collection of objects that contains both, the newest entry where id=='a', and the newest entry where id=='b'?
[Update: The idea is to avoid having to query the database multiple times (i.e. once for each name).]
"How do I query the database such that I get returned a collection of objects that contains the newest where id=='a'"
db.collection.find({ name : 'a' }).sort({ timestamp : -1 })
"and the newest entry where id=='b'?"
db.collection.find({ name : 'b' }).sort({ timestamp : -1 }).limit(1)