Mongoose $push add to document - mongodb

I'm trying to add an element to an existing array, but it produces an error:
The field 'data' must be an array but is of type object in document
Scheme:
const testScheme = new Schema({
user: {
type: String,
required: true
},
data: [{
platform: {
type: String,
required: true
},
item_name: {
type: String,
required: true
},
price: {
type: Number,
default: 0
},
updatedAt: Date
}]
}, {
versionKey: false,
timestamps: true
});
Document in mongodb:
"data": [{
"price": 50,
"_id": "5a84268d6c78a60c10479437",
"platform": "pl1",
"item_name": "test"
}],
"_id": "5a841bccb44cb8cd5b974d71",
"user": "Ivan",
"updatedAt": "2018-02-14T12:07:41.793Z",
"createdAt": "2018-02-14T11:21:48.104Z"
Query:
var item = {
"platform": "pl700",
"item_name": "someText",
"price": 700,
"updatedAt": new Date()
};
Data.findOneAndUpdate({
'user': 'Ivan'
}, {
$push: {
'data': item
}
}, {
safe: true,
upsert: true
},
function(err, data) {
if (err) return res.status(500).send({
'error': err
});
res.status(200).send({
'data': data
});
}
);
I trying query with $set parametr and it works, but $push, $addToSet didn't work for me. Also i tried to google this problem and can't solve it.

It is not clear what you are intending to do.
To push an item into array you use $addToSet/$push. For updating a array you use $set.
Using $set you can update the whole document or you can update the specific field.
Update whole doc
Data.findOneAndUpdate({
'user': 'Ivan',
'data._id':item._id
}, {
$set: {
'data.$': item
}
}...
)
Update specific field
Data.findOneAndUpdate({
'user': 'Ivan',
'data._id':item._id
}, {
$set: {
'data.$.price': item.price
}
}...
)

Related

Update using positional operator ($) in mongoose

I have a document containing an array of objects. I wanted to update a particular element in the array. Tried using MongoDB shell, it works fine. But when I use in Mongoose in NodeJs, it is not working. The command is same in both the cases.
NodeJs code
const updateAttendance = await classModel.updateOne(
{
_id: item.classId,
'studentAttendance.studentId': item.studentId,
},
{ $set: { 'studentAtendance.$.present': true } }
)
Schema defination
const mongoose = require('mongoose')
const moment = require('moment')
const student = mongoose.Schema({
studentId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
unique: true,
},
present: {
type: Boolean,
default: false,
},
})
const classes = mongoose.Schema({
date: {
type: String,
required: true,
default: moment().format('DD/MM/YYYY'),
validate: {
validator: (value) => {
return moment(value, 'DD/MM/YYYY', true).isValid()
},
message: 'Provide a valid date in the format of DD/MM/YYYY',
},
},
courseId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Course',
},
studentAttendance: [
{
type: student,
},
],
})
module.exports = mongoose.model('Class', classes)
Sample data
{
"date": "20/06/2021",
"_id": "60cf5446970dc063e40356d3",
"courseId": "60ce2c3aca275c868089ac48",
"studentAttendance": [
{
"present": false,
"_id": "60cf5446970dc063e40356d4",
"studentId": "60ce315f9f83a24544414705"
},
{
"present": false,
"_id": "60cf5446970dc063e40356d5",
"studentId": "60ce31ba9f83a2454441470a"
},
{
"present": false,
"_id": "60cf5446970dc063e40356d6",
"studentId": "60ce38e49f83a24544414712"
}
],
"__v": 0
}
What am I doing wrong or where is the problem?
Without looking at the schema def, just taking a punt in the dark that you dont explicitly say its an ObjectId.
Easy solve, just wrap "item.studentId" in mongoose.Types.ObjectId().
So your new code would be like
const updateAttendance = await classModel.updateOne({
_id: mongoose.Types.ObjectId(item.classId),
'studentAttendance.studentId': mongoose.Types.ObjectId(item.studentId),
},
{ $set: { 'studentAtendance.$.present': true } }
)
Don't forget const mongoose = require('mongoose');
Based on the update your update statement needs 'updating'. try fixing the spelling of studentAttendance vs studentAtendance in the $set statement.

Update a key value inside an array in Mongodb

I'm having problems trying to update from mongoDB the "name" key inside gardens.
{
name: "Adky",
email: "dry#fsdf.co.uk",
lastConected: "",
gardens: [{
name: '',
location_id: "43567",
plants: []
}, {
name: '',
location_id: "234092",
plants: []
}, {
name:'',
location_id: "22355",
plants: []
}]
}
I tried
collection
.findOneAndUpdate({
_id: ObjectId(id)
},{
"gardens.location_id": req.params.location_id
}, {
$set: {
"gardens.$.name": updatedData.name
}
}, {
returnOriginal: false
}
But This error comes up
{
"status": 500,
"error": {
"driver": true,
"name": "MongoError"
}
}
Don't really know what to do here..
I was thinking that the problem should be in the way I'm accessing into gardens.
FindOneAndUpdate takes 3 parameters
db.collection.findOneAndUpdate(
<filter>,
<update document or aggregation pipeline>, // Changed in MongoDB 4.2
{
projection: <document>,
sort: <document>,
maxTimeMS: <number>,
upsert: <boolean>,
returnNewDocument: <boolean>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
but you are passing 4 parameters, you can update your code
collection
.findOneAndUpdate({
_id: ObjectId(id), "gardens.location_id": req.params.location_id
}, {
$set: {
"gardens.$.name": updatedData.name
}
}, {
returnOriginal: false
})
You can find your document using both _id and location_id.
Please use that code
db.testers.findOneAndUpdate({
_id: ObjectId("5dee7d425a13b401c7722c28")
,
"gardens.location_id": "234092"
}, {
$set: {
"gardens.$.name": 'tst34'
}
})
db.getCollection('CollectionName').update_one(
{"gardens.name": '' },
{$set: {"gardens.name" : "New_Name"}})

Return true/false if users id is found in array of objects

I am new with mongodb. I am saving user recommendations in below schema. I am saving date on which user liked the business. I only want to return true/false if user id (uid) is present in users array.
const userSchema = new Schema({
uid: { type: String},
createdAt: { type: Date, default: Date.now() },
_id: false
});
const businessRecommendationsSchema = new Schema({
businessID: { type: String, unique: true},
users: [userSchema]
},{
timestamps: true
});
I do not want to return whole object if present but only true of false. Please help.
Sample data:
{
"businessID": "35M1L66a8YXzKmDYvbya3sHGJkH2",
"updatedAt": {
"$date": "2017-09-27T10:03:01.866Z"
},
"createdAt": {
"$date": "2017-09-27T10:03:01.866Z"
},
"users": [
{
"uid": "PFwwUecwpFhhWCbJEaFjmfnGOix1",
"createdAt": {
"$date": "2017-09-27T10:03:01.867Z"
}
}
]
}
I tried below query but this only works if it is simple array not array of objects.
Business.aggregate()
.match({ businessID: req.params.businessID })
.lookup({ from : 'businessrecommendations', localField: 'businessID', foreignField: 'businessID',
as: 'recommendations' })
.project({_id: 0, businessID: 1, businessName: 1,
recommendedBy: { $arrayElemAt: [ "$recommendations", 0]}})
.project({_id: 0, businessID: 1, businessName: 1,
recommended: { $in : [req.query.uid, "$recommendedBy.users"]}});

How to populate multilevel array in mongoose

I have a Quiz Model with array of Section and each Sections has array of reference to Question.
I want to populate Quiz with question.
QuizModel
var quizSchema = new Schema({
name: String,
code: Number,
creator: String,
createdBy: { type: Schema.Types.ObjectId, ref: 'user' },
section:[{
title: String,
questions: [{type: Schema.Types.ObjectId ,ref: 'question'}]
}],
createdOn: {type:Date, default:Date.now}
});
and questionModel
var questionSchema = new mongoose.Schema(
{
question: String,
answer: [String],
correct: Number,
createdOn: {type:Date, default:Date.now}
});
I have following the official mongoose documentation for populating
http://mongoosejs.com/docs/populate.html#deep-populate
My attempt
quizSchema.find({_id: quiz_id})
.populate({
path: 'section' ,
populate: {
path: 'section.questions',
model: 'questionSchema'
}
})
.exec( function (err, result) {
if (err) return done(err,null);
console.log("list of questions are" + result);
return done(err, result);
});
}
The output I am getting is list of question's id not the actual question.
{
"status": "success",
"message": "Quiz data",
"result": [
{
"_id": "57fd5912ec0ad6bc8b67d71c",
"name": "My Quiz",
"creator": "foo",
"__v": 0,
"code": 124,
"createdOn": "2016-10-11T21:26:42.774Z",
"section": [
{
"_id": "57fd7e82c20a2fe5da3ed569",
"questions": [
"57fd7f8560e98fe710878820",
"57fd7f9d60e98fe710878821",
"57fd81408b20dae9108d347c",
"57fd81408b20dae9108d347d",
"57fd826aea5159ea5ff2f1a9",
"57fd82ab0dbc0feaa753e50c",
"57fd82efd789afeb0353f036",
"57fd84b0fef6a2ed21fad5ae",
"57fd84cc5dab10ed471bcaf5",
"57fd84cd5dab10ed471bcaf6"
]
},
{
"title": "next section",
"_id": "57fff1e0f1913138c27e50a0",
"questions": [
"57fff242f1913138c27e50a1"
]
}
]
}
]
}
I think I am doing something wrong with populate field, but not sure .
Just alter your query to
quizSchema.find({_id: quiz_id})
.populate({
path: 'section.questions'
})

Meteor Mongo add subdocument

I have a collection documents MasterPropinsis like this :
{
"_id": "4HSb7bbjFBzRSftXu",
"nama": "Yogyakarta",
"kabupaten": [
{
"id": "KulonProgo",
"nama": "Kulon Progo",
"kecamatan": [{ "nama": "Kalibawang" },{ "nama": "Nanggulan" }]
},
{
"id": "Sleman",
"nama": "Sleman",
"kecamatan": [{ "nama": "Depok" },{ "nama": "Berbah" }]
},
{
"id": "Bantul",
"nama": "Bantul",
"kecamatan": []
}
]
}
At kabupaten:Bantul, I want to Add subdocument kecamantan:XXX, with this code :
Masterpropinsis.update(
{
_id: Session.get('idKabupaten').toString(),
'kabupaten.id': Session.get('idKecamatan').replace(" ", "")
},
{
$addToSet: {
'kabupaten.kecamatan': {
nama: nama,
createdAt: new Date(),
createBy: CreateBy,
createByID: CreateByid
}
}
},
{
validate: true
});
But I get this error:
Uncaught Error: Not permitted. Untrusted code may only update documents by ID. [403]
Here is an example try this
var docId = Session.get('idKabupaten'); // usally toString is not nesserry unless you do something unusual
Masterpropinsis.update({_id: docId }, {
$push: {
'kabupaten.kecamatan': {
nama: nama,
createdAt: new Date(),
createBy: CreateBy,
createByID: CreateByid
}
}
}); // validate true also is the default unless again you do something unusual
you can see we only supply {_id: docId} in the selector the error says in client you can only update by the ID in the server you can do any selector. Also hopefully you can have Allow/Deny rules to allow updates from the client? http://docs.meteor.com/#/full/allow