I have been facing some problem while updating the data in the db using mongoose, Therefore thanks in advance for the help.
I have been sending some data from a dynamic form that contains different set of fields each time... but when i update the array in the db it changes those fields.
This was my controller function earlier:-
exports.savePageContent = (req, res, next) => {
const id = req.body.dest; // getting page data document id
delete req.body.dest;
var arr = [];
// When we are returning the same page each time after we submit the data for the particuklar section form then how are we supposed to redirect the user to next page once he is done doing all
var fieldKeys = Object.keys(req.body);
for(let i = 0; i < fieldKeys.length; i++)
{
arr.push({fieldRef : fieldKeys[i], fieldValue : req.body[fieldKeys[i]]});
}
pageDataModel.findByIdAndUpdate(id, {pageData : arr}).exec(function(err, result) {
if(err){
console.log(err);
}
else {
console.log("data is inserted");
req.flash('message', "Data Saved Successfully");
}
})
}
I also tried a few updates and then moved to this portion
This is my new controller function :
exports.savePageContent = (req, res, next) => {
const pageid = req.body.dest; // getting page data document id
delete req.body.dest;
var fieldRefData = "";
var fieldValueData = "";
var fieldKeys = Object.keys(req.body);
for(let i = 0; i < fieldKeys.length; i++)
{
fieldRefData = fieldKeys[i];
fieldValueData = req.body[fieldKeys[i]];
try{
pageDataModel.update({id : pageid, "pageData.fieldRef" : fieldRefData}, {$set : {"pageData.$.fieldValue" : fieldValueData }}, {upsert : true}).exec(function(err, result) {
if(err){
console.log(err);
}
else {
console.log("data is inserted", result);
}
});
req.flash('message', "Data Saved Successfully");
}catch(e){
console.log(e);
req.flash('message', "error Occurred updating Data ");
}
}
}
To elaborate the case for better understanding:-
This is the data that comes first time in the body
[
{ fieldRef: 'sec1.1.h1', fieldValue: 'this is the field value 1' },
{ fieldRef: 'sec1.1.p', fieldValue: 'this is the field value 1' },
{ fieldRef: 'sec1.1.a', fieldValue: 'this is the field value 1' },
{ fieldRef: 'sec1.2.h2', fieldValue: 'this is the field value 1' }
]
and This is the data that comes the second time :-
[
{ fieldRef: 'sec2.1.h1', fieldValue: 'this the field value 2' },
{ fieldRef: 'sec2.1.p', fieldValue: 'this the field value 2' },
{ fieldRef: 'sec2.1.a', fieldValue: 'this the field value 2' },
{ fieldRef: 'sec2.2.h1', fieldValue: 'this the field value 2' }
]
when i want both the data's in the db but when i send one the second data the first one gets updated to the second one and vice versa..
this is the db images of the scenario
this is the data in the document on the first operation
this is the data in the document on the second operation
i am not able to keep and update them both... so please help me ...
This is the error that I am getting most of the time which says that the query is wrong
MongoServerError: The positional operator did not find the match needed from the query.
at /home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/operations/update.js:80:33
at /home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/cmap/connection_pool.js:272:25
at handleOperationResult (/home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/sdam/server.js:370:9)
at MessageStream.messageHandler (/home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/cmap/connection.js:479:9)
at MessageStream.emit (events.js:400:28)
at processIncomingData (/home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/cmap/message_stream.js:108:16)
at MessageStream._write (/home/pushkar/Desktop/NodejsWebApp1/node_modules/mongodb/lib/cmap/message_stream.js:28:9)
at writeOrBuffer (internal/streams/writable.js:358:12)
at MessageStream.Writable.write (internal/streams/writable.js:303:10)
at Socket.ondata (internal/streams/readable.js:731:22) {
index: 0,
code: 2
}
Also if I was unable to make my scenario clear please leave a comment and I will try to explain it more clearly..
thanks In Advance
I hope this should solve the issue :
pageDataModel.updateOne({_id : "61d73f31cb5681b85618995a", "pageData.fieldRef" : "sec2.c" },{"$set" : {"pageData.$.fieldValue" : "Mkc" }}).exec(function(err, result) {
if(err) throw err;
else {
console.log(result);
}
});
$set will replace a new value for the key. If you use the 3rd value then the $set will replace the 3rd value, use $push instead of $set operator.https://docs.mongodb.com/manual/reference/operator/update/push/
Try using _id instead of id.
pageDataModel.update({_id : pageid, "pageData.fieldRef"}) {
Or even pageData._id instead of id.
pageDataModel.update({'pageData._id' : pageid, "pageData.fieldRef"}) {
Furthermore, your id is a string in the query, but an object id in database, so call a helper.
pageDataModel.update({'pageData._id' : mongoose.Types.ObjectId(pageid), "pageData.fieldRef"}) {
Related
In my To-Do app, when a logged-in User completes a task, I would like to clear it from the MongoDB database.
Here is the code for my Schema.
const user = new mongoose.Schema({
username : String,
password : String,
task : [{
text : String,
day : String,
reminder : Boolean,
]}
})
For example, if Daryl completed text : "Gym" & day : "Feb 4th 5.30pm", I would like to only remove task[0] from Daryl's task Array.
Here is my attempt at doing so using Mongoose,
app.delete("/tasks", (req,res) => {
User.findOne( {_id : req.user.id}).then((target) => {
target.task.remove({text : req.body.text, day : req.body.day})
})
})
User.findOne({_id : req.user.id}) to only target the person that logged in
Once targeted, access task array using .task
and use .remove along with filters, to remove that entry from the array
I have console.logged() all the variables and it tallies with the data fields, however the entry is not being removed. What am I doing wrong?
I managed to solve my problem, hopefully this helps someone else
app.delete("/tasks", (req, res) => {
User.findByIdAndUpdate(req.user.id, {$pull: {"task": {text: req.body.text}}}, {safe: true, upsert: true},
function (err, node) {
// console.log here for debugging, if you want
})
})
This successfully erases items based on
req.user.id
"task" : {//whatever your stricter conditions are}
I still don't understand why my earlier attempts failed, but at least this one works.
I am trying to implement a DynamoDB based application to store some request data. I read the DynamoDB official documentation and currently I am following this official tutorial to do some basic operations.
I am using a local DynamoDB docker container. You can run it with this:
docker run -d -p 8000:8000 amazon/dynamodb-local:latest -jar DynamoDBLocal.jar -sharedDb
When I try to create a new table just same as the tutorial I gave above, I got no error, everything is fine:
var params = {
TableName: 'book',
KeySchema: [
{
AttributeName: 'title',
KeyType: 'HASH',
}
],
AttributeDefinitions: [
{
AttributeName: 'title',
AttributeType: 'S'
}
],
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
}
};
dynamodb.createTable(params, function(err, data) {
if (err) print(err); // an error occurred
else print(data); // successful response
});
But when I try to put some new items in it:
var params = {
TableName: 'book',
Item: { // a map of attribute name to AttributeValue
title: "Sample Application: CloudList",
chapter: 10
}
};
dynamodb.putItem(params, function(err, data) {
if (err) print(err); // an error occurred
else print(data); // successful response
});
I got this error:
31 validation error actually is equal to number of chars in title: Sample Application: CloudList. DynamoDB shell also did not recognized the print function which is given in the above tutorial. So I had to replace it with ppJson function. Where am I doing wrong and how can I put/delete/get items from DynamoDB via Web Shell? (and also via PHP code)
Edit: I also tried what Vikdor said in the comment, it seems I got rid of that UnexpectedParameter error but this time I got Invalid attribute value type error.
var params = {
TableName: 'book',
Item: { // a map of attribute name to AttributeValue
'title': {S: "Sample Application: CloudList"},
'chapter': {N: '10'}
}
};
This doc explains the structure of the Item key in the params passed to the API and your params should be as follows:
var params = {
TableName: "book",
Item: {
"title": {"S": "Sample Application: CloudList"},
"chapter": {"N": :10"}
}
};
Note that even the numbers should be enclosed in quotes.
Is there a way for MongoDB to search an entire collection's keys' contents using only a single search keyword?
Suppose I have the following collection (let's call it foodCollection):
{
name: "Chocolate Mousse Cake",
type: "Cake"
},
{
name: "Mother's Cookies",
type: "Cookies"
},
{
name: "Dark Bar",
type: "Chocolate"
}
I want my search to look for matches that contain "Chocolate", meaning it should return "Chocolate Mousse Cake" and "Dark Bar".
I'm trying to do this using the ff: code:
Client-side controller
// Search Products
$scope.searchProduct = function () {
$http.get('/api/products/search/' + $scope.searchKeyword).success(function(data){
console.log(data);
})
.error(function(err) {
console.log("Search error: " + err);
});
}
Express.js
app.get('/api/products/search/:param', productController.search); // Search for product
Server-side controller (I used this reference from the MongoDB docs):
// Search
module.exports.search = function(req, res) {
console.log("node search: " + req.body);
Product.find({ $or: [{productName: req.body},
{productType: req.body}]
}, function(err, results) {
res.json(results);
});
}
When I executed this, I got nothing. Am I missing something?
Any help would be greatly appreciated. Thank you.
UPDATE (FINAL)
Finally solved this thanks to Joydip's and digit's tips. Here's my solution in case somebody else gets the same problem as I did:
Client-side controller
$scope.searchProduct = function () {
if ($scope.searchKeyword == '') {
loadFromMongoDB(); // reloads original list if keyword is blank
}
else {
$http.get('/api/products/search/' + $scope.searchKeyword).success(function(data){
if (data.length === 0) {
$scope.showNoRec = true; // my flag that triggers "No record found" message in UI
}
else {
$scope.showNoRec = false;
$scope.productList = data; // passes JSON search results to UI
}
});
}
}
Express.js
app.get('/api/products/search/:keyword', productController.search); // Search for product
Mongoose schema
var mongoose = require('mongoose');
var schema = new mongoose.Schema({
productName: String,
productType: String,
productMaker: String,
productPrice: Number,
createDate: Date,
updateDate: Date
});
schema.index({productName: "text", productType: "text", productMaker: "text"});
Server-side controller
module.exports.search = function(req, res) {
Product.find({$text: {$search : req.params.keyword}}, function(err, results){
res.json(results);
})
}
Thank you everyone for your help. :)
You can try by creating an Index:
db.yourollection.createIndex({"productName":1,"productType":1})
And then by searching for the value, Example:
Product.find({$text:{$search: 'Chocolate'}},{productName:1, productType:1});
If you want to search all key, then you can use
db.foodCollection.createIndex( { name: "text", description: "text" } )
then search by
db.foodCollection.find({ $text: { $search: "choco" } })
I am trying to insert document in a collection. The structure of the document looks like this:
[{
"observationNum" : 1231,
"observation_data": [{
"child_id": 1234,
"child_observation_data": [{
"activity_performed": true,
"observation_date": 15062016,
"teacher_id": 6789
}]
}]
}]
To achieve this, I have created 3 models. A Model named child_observation_data containing it's data as shown in the JSON structure above. Another Model named observation_data containing child_id and child_observation_data. I am trying to insert the data in the collection as shown below however the data isn't inserted in the observation_data model and child_observation_data model. What am I doing wrong?
function insertData() {
var childObservationDataModelObject = ChildObservationData.ChildObservationData({"activity_performed": true, "observation_date": "17May2016", "teacher_id":789});
var observationDataModelObject = ObservationData.ObservationData({"child_id" : 21386, "child_observation_data":childObservationDataModelObject});
var activityModelObject = new ActivityModel({"observationNumber" : 123456, "observation_data": observationDataModelObject});
activityModelObject.save(function(err, savedObject) {
if(err) {
console.error("error in saving:", err);
return;
}
if(savedObject != null)
console.log("Data saved ", savedObject);
});
ObservationData.getObservationDataModel()
.findOne({"child_id" : 21386})
.populate('child_observation_data')
.exec(function (err, activity) {
if (err)
console.log("error in finding", err);
console.log('The creator is ', activity);
});
}
The console logs are:
Data saved { observation_data: [ 57eb905265ddc958133ac649 ],
_id: 57eb905265ddc958133ac64a,
observationNumber: 123456,
__v: 0 }
The creator is null
With this document :
{
"_id" : 8,
"updatedAt" : ISODate("2016-04-13T05:07:38.905Z"),
"createdAt" : ISODate("2016-04-13T04:15:37.612Z"),
"author" : "test#test.com",
"urgency" : "slow",
"state" : "pending",
"comment" : "",
"requests" : [
{
"value" : 1,
"product" : "Slethoxynal",
"_id" : ObjectId("570dc7e91d15852f1c2ae66a")
},
{
"value" : 1,
"product" : "Thyrploxynénol",
"_id" : ObjectId("570dc7e91d15852f1c2ae66b")
}
],
"__v" : 0
}
I use this javascript function :
function closeRequest(req, res, next) {
Request.findOne({ '_id': req.body.id}, function(err, request){
debug(request);
debug("Length is %s", request.requests.length);
for(var i=0;i<request.requests.length;i++){
debug("We validate the element %s of the request %s", i, req.body.id);
console.log(i);
Material.findOne({'title': request.requests[i].product}).exec(function(err, material){
debug("Inside i is : %i",i);
debug("Product is %s", request.requests[i].product);
debug("Material found is %s", material.title);
material.amount -= request.requests[i].value;
material.save(function(err) {
if(err)
res.send(err);
});
});
}
request.state='accepted';
request.save(function(err) {
if(err)
res.send(err);
});
});
res.redirect('back');
}
And my console prints :
0
1
Inside i is 2
Then the function crashes with
TypeError: Cannot read property 'product' of undefined
At line
debug("Product is %s", request.requests[i].product);
The goal of this function is to validate one request (we put its state from 'pending' to 'accepted'). But as we do that, the stocks in the warehouse needs to be decremented (the 'amount' parameters).
It seems pretty logical that we cannot access the product property since i had a value of 2 and there is no third element in our array.
But why is my iteration variable going out of its range ? And how can i solve that ? The fact that the console prints "Inside" only once makes me wonder if it's not another asynchronous problem.
This is a problem about async execution of your code. In particular the for loop "triggers" multiple async functions and continuous execution. After looping through your loop i===2. As the first Material.findOne callback gets executed requests[2] === undefined (as requests.length === 2) throws your error.
I'd suggest to go like this:
var updateMaterialFns = request.requests.map(function(req, i) {
return function(done) {
debug("We validate the element %s of the request %s", i, req.body.id);
console.log(i);
Material.findOne({'title': req.product}).exec(function(err, material){
if (err) {
done(err)
}
debug("Inside i is : %i",i);
debug("Product is %s", request.requests[i].product);
debug("Material found is %s", material.title);
material.amount -= request.requests[i].value;
material.save(done)
})
}
})
async.parallel(updateMaterialFns, function(err) {
if (err) {
res.send(err)
}
})
async is a node/npm module featuring many functions to deal with the execution and control flow of async programming.