Code created in Mongoose to update a subdocument was not working. So I tried to update the subdocument within the Mongo Shell.
This is the document (location) and subdocument (review):
{
"_id" : ObjectId("56d8c73314fbc7e702cfb8c4"),
"name" : "Costly",
"address" : "150, Super Street",
"coords" : [
-0.9630884,
51.451041
],
"reviews" : [
{
"author" : "kyle riggen1",
"_id" : ObjectId("56d8de74cc7f953efd8455d9"),
"rating" : 4,
"timestamp" : ISODate("2015-06-01T06:00:00Z"),
"reviewText" : "will the ID work?"
}
],
"rating" : 0,
"__v" : 2
}
Here are some of my attempts at updating the subdocument:
This question gave this format:
update({
_id: "56d8c73314fbc7e702cfb8c4",
"reviews._id": ObjectId("56d8de74cc7f953efd8455d9")
},{
$set: {"reviews.$.rating": 1}
}, false, true
);
This returned an error of "update is not defined" as shown:
2016-03-03T22:52:44.445-0700 E QUERY [thread1] ReferenceError: update is not defined :
#(shell):1:1
Which I think is because the command did not start with db.locations.update()
MongoDB documentation used this format:
db.locations.update(
{
_id: "56d8c73314fbc7e702cfb8c4",
review: { $elemMatch: { author: "kyle riggen1" } }
},
{ $set: { "location.$.rating" : 1 } }
)
This returns a valid update but the update didn't actually happen as shown:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
This question used this format:
db.locations.update({
_id: "56d8c73314fbc7e702cfb8c4",
'review.author': 'kyle riggen1'
},
{ $set: { 'review.$.rating': 1 }}
)
This returns the same as the MongoDB documentation as shown here:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
So these queries I guess are working but my data is not getting updated. Would my data be indexed wrong perhaps? The actual location is able to be updated even through a Mongoose API.
You can do it By $push Or $addToSet.
db.col.update(
{ name: 'reviews', 'list.id': 2 },
{$push: {'list.$.items': {id: 5, name: 'item5'}}}
)
See the reference from mongodb Manual
https://docs.mongodb.org/manual/reference/operator/update/push/
Please know db.collection.update( criteria, objNew, upsert, multi )
criteria: match condition
objNew: update content
upsert: true or false
true : if not existed, insert it
false : if not existed, don't insert
multi: true or false
true : update all matched documents
false : only update the first matched document
Related
I have below json data and want to update the value according to the condition
{
"_id" : ObjectId("5fce2d4c7b2ea2e79ercvju4"),
"userId" : 1,
"token": "jwt_token_value",
"isActive" : 0,
"__v" : 0
}
{
"_id" : ObjectId("5fce2d4c7b2ea2e79ercvjk0"),
"userId" : 1,
"token": "jwt_token_value",
"isActive" : 0,
"__v" : 0
}
{
"_id" : ObjectId("5fd0d45tjd82a02dd0f17fc4"),
"userId" : 1,
"token": "jwt_token_value",
"isActive" : 1,
"__v" : 0
}
I have managed the things as below.
let update = await UserDetails.findAndModify(
{ userId: 1, token: token },
[],
{$set: { isActive: 0 }},
{ new: true }
);
=> This query should update the last json collection key of isActive to 1. But it is not updating the values any how. What the things that I am doing wrong ? It is not throwing me any error as well to debug.
I am following this answer: https://stackoverflow.com/a/24648693/5624578
You can include the query identifiers to specify what each section is doing like this:
let update = await UserDetails.findAndModify(
query: { userId: 1, token: token },
update: {$set: { isActive: 0 }},
upsert: true
);
Hi i need a help for mongodb update multiple records in one query by array value:
For This Data
{
"_id" : ObjectId("5edcd82197ace301c45ccb02"),
"date" : NumberInt(20200607),
"result" : [
{
"_id" : ObjectId("5edcd82197ace301c45ccb03"),
"balance" : NumberInt(300),
},
{
"_id" : ObjectId("5edcd82197ace301c45ccb04"),
"balance" : NumberInt(200),
}
]
}
Query
use auth;
db.getCollection("dailyreportbalace").updateMany(
[{
"_id": ObjectId("5edcd82197ace301c45ccb02"),
"result._id": ObjectId("5edcd82197ace301c45ccb03")
},{
"_id": ObjectId("5edcd82197ace301c45ccb02"),
"result._id": ObjectId("5edcd82197ace301c45ccb04")
}],
[{
"$set": { "result.$.balance": NumberInt(60) }
},{
"$set": { "result.$.balance": NumberInt(80) }
}],
{upsert: true, multi: true}
)
Error Query
E QUERY [js] Error: the update operation document must contain atomic operators :
Please consider my comment.
You are doing it wrong, if you look at the update docs, the first parameter is query, and it can't be an array.
You need to use filtered positional operator. Something like below:
db.getCollection("dailyreportbalace").updateMany(
{"_id": ObjectId("5edcd82197ace301c45ccb02")},
{
"$set": {
"result.$[elem1].balance": NumberInt(60),
"result.$[elem2].balance": NumberInt(80) }
},
{
upsert: true,
multi: true,
arrayFilters: [
{"elem1._id": ObjectId("5edcd82197ace301c45ccb03")},
{"elem2._id": ObjectId("5edcd82197ace301c45ccb04")}]
}
)
I am trying to use Mongoose findByIdAndDelete() method on a model but it does not see the _id it needs to delete.
My route is declared similar to this (minified) example:
router.delete('/delete-entity/:id', (req, res) => {
Entity.findByIdAndDelete(req.params.id)
.exec()
.then((docs) => { ...handle success })
.catch((err) => { ...handle error });
});
I only have middleware running that hooks into the save method of the model. But this middleware does not touch the _id field.
When I console.log() inside the route I can see that req.params.id is set. Also if I try to identify my document using an other field to delete it (so not the _id field), it does works. However when I try to use the _id field all that is returned to the client is ''. This makes me believe that something goes wrong in comparing datatypes of the _id field. But cating using mongoose.Type.ObjectId() did not help either.
What could be going on here?
In addition to this already provided information. Here is my model.
const embeddedEntity = new mongoose.Schema({
name: { type: String, required: true }
}, { _id: false });
const entity = new mongoose.Schema({
name: { type: String, required: true },
embeddedInfo: { type: embeddedEntity, required: true }
});
module.exports = mongoose.model('Entity', entity);
#Invider I managed to get this from the profiler.
{
"op" : "command",
"ns" : "development.entities",
"command" : {
"findAndModify" : "entities",
"query" : {
"_id" : ObjectId("5dc95b8cc472d31232dba5a3")
},
"new" : false,
"remove" : true,
"upsert" : false,
"lsid" : {
"id" : UUID("30086660-0619-440e-9268-148957428a2b")
},
"$db" : "development"
},
"keysExamined" : 0,
"docsExamined" : 0,
"ndeleted" : 0,
"numYield" : 0,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(1),
"w" : NumberLong(1)
}
},
"Database" : {
"acquireCount" : {
"w" : NumberLong(1)
}
},
"Collection" : {
"acquireCount" : {
"w" : NumberLong(1)
}
}
},
"responseLength" : 74,
"protocol" : "op_msg",
"millis" : 0,
"planSummary" : "IDHACK",
"execStats" : {
"stage" : "DELETE",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"nWouldDelete" : 0,
"nInvalidateSkips" : 0,
"inputStage" : {
"stage" : "IDHACK",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keysExamined" : 0,
"docsExamined" : 0
}
},
"ts" : ISODate("2019-11-14T09:27:52.988Z"),
"client" : "127.0.0.1",
"allUsers" : [ ],
"user" : ""
}
A lot of thanks goes out to #invider and #SuleymanSah for pointing me into the right direction.
The problem was actually something pretty simple that I completely overlooked and was indeed related to the datatype as I expected.
My e2e tests were failing because of the same problem as trying to call the route using Postman.
The problem was that when adding test samples to the database I was setting the _id field myself. This most likely causes the value stored to be of type string. Letting MongoDB itself set the _id field solved this issue. At least for working in the live environment using Postman.
For my e2e test I had to modify my the data that will be loaded into the database for each test. I was adding samples in the following way:
{
_id: '5dc95b8cc472d31232dba5a5',
name: 'SomeData',
embeddedInfo: {
name: 'someOtherData'
}
}
I should have casted the _id into an ObjectId first. Like so:
{
_id: mongoose.Types.ObjectId('5dc95b8cc472d31232dba5a5'),
name: 'SomeData',
embeddedInfo: {
name: 'someOtherData'
}
}
Again. Thanks to the both of you.
i am not able to query results in this query,
i want result based on detail.type (like fetch record where detail.type="one") and fetch only first 10 records in detail.numbers array
{
"_id" : ObjectId("5a27b609e101b6092b4ebf91"),
"city" : "Mumbai",
"detail" : [
{
"type" : "One",
"name" : "Some name",
"_id" : ObjectId("5a27b609e101b6092b4ebf92"),
"numbers" : [
"72598xxx78",
"81301xxx88",
"83302xxx30",
"84309xxx43",
"85309xxx77",
"86309xxx61",
"87270xxx88",
"85272xxx36",
"88272xxx23",
"85276xxx01"
]
},
{
"name" : "Some name",
"type" : "two",
"_id" : ObjectId("5a28e954d4f5a30527d92a32"),
"contact" : [
"72598xxx78",
"81301xxx88",
"83302xxx30",
"84309xxx43",
"85309xxx77",
"86309xxx61",
"87270xxx88",
"85272xxx36",
"88272xxx23",
"85276xxx01"
]
},
]
}
MongoDB facilitates querying over array elements using $elemMatch operator.
According to description as mentioned into above question as a solution to it please try executing following MongoDB query to fetch required data from MongoDB collection.
db.collection.find({
detail: {
$elemMatch: {
type: 'One'
}
}
}, {
_id: 1,
city: 1,
'detail.$': 1
})
db.collection.aggregate([
{
$project:{
detail:{
$map:{
input:{$filter:{input:"$detail",as:"d",cond:{$eq:["$$d.type","One"]}}},
as:"d",
in:{
"type" : "$$d.type",
"name" : "$$d.name",
"numbers":{$slice:["$$d.numbers",10]}
}
}
}
}
}
])
Hi I have mongodb query like this .
.aggregate(
[
{ $match : { comment_box : "somdata" } },
{ $project : {
comment : 1,
created_at: 1,
current_date: "$replies.created_at",
},
dateDifference: { $subtract: [ new Date(), "$created_at"] }
}},
]
)
Imagine that I want to get created_at value from replies array in current date field. but this query returns
current_date: [
"2016-03-08T13:48:27.882Z",
"2016-03-08T14:26:22.194Z"
]
instead of current created_at value of each element from this array
I have tried many ways but got errors
current_date: "$replies.0.created_at",
current_date: "$replies.$.created_at",
current_date: "$$replies.created_at",
and etc
please help me to retrieve data like this
current_date:"2016-03-08T13:48:27.882Z",
I’m assuming you want the latest comment date. In that case, you can just take the $max:
current_date: { $max: '$replies.created_at' }
Demo:
> db.comments.insert({_id: 0, replies: [{created_at: new Date('2017-04-03')}, {created_at: new Date('2017-02-03')} ]})
WriteResult({ "nInserted" : 1 })
> db.comments.insert({_id: 1, replies: []})
WriteResult({ "nInserted" : 1 })
> db.comments.aggregate([{$project: {current_date: {$max: '$replies.created_at'}}}])
{ "_id" : 0, "current_date" : ISODate("2017-04-03T00:00:00Z") }
{ "_id" : 1, "current_date" : null }
Notice how the document with an empty replies array gets null.