Mongoldb, issue with deleting and saving data to a collection - mongodb

I am having some issue with removing objects in my database. I have a collection called menus which consists of several object where each object is an item in the menu. Here is how it looks :
{
"_id":ObjectId("583b7577e1206be8ee79f062"),
"restID":"583972080daa6ece0960778c",
"itemName":"buffallo chicken wings",
"subType":"Appetizers/Starters",
"cuisine":"American",
"description":"descritption of buffallo chicken wings",
"duration":"All",
"quantity":"6",
"cost":"10.95",
"__v":0
}
Now I have a X button next to each item in my frontend. The code below shows how I am trying to delete an item (when user clicks the X button) on my server side. After debugging this I observed that it is splicing the object that I want to delete but it is not updating the database. I don't understand why. Am I doing something wrong?
module.exports.removemenu = function(req, res) {
var menuId = req.body.itemId;
Menu.find({}, function(err, results){
results.map(function(menu, index){
if(menu._id == menuId) {
results.splice(index, 1);
}
menu.save();
})
res.json({res: 'success', data: results});
})
}

Are you upserting the changes to the database afterwards?

Use remove command to delete record from collection
db.restaurants.remove( { "borough": "Manhattan" } )

Related

Latency compensation and Firestore transactions

I have an onSnapshot keeping track of the documents in a collection:
db.collection('/.../').onSnapshot(querySnapshot=> mylocalvariable = querySnapshot.docs)
Now, I want to select the first (in some order) element of this collection of documents that my user has not yet handled. When a user is done handling a document, I use a transaction to update the document according to the user's needs (transaction is better for me than .update() because I might have multiple users changing different parts of the document).
The problem is that unlike a .update (which would update mylocalvariable immediately), it seems like the transaction finishes without updating mylocalvariable. So, when I go to grab the "next" document, it just grabs the same document, because the function runs before the variable gets updated.
Code sample:
db.collection('/mycollection').onSnapshot(querySnapshot=> mylocalvariable = querySnapshot.docs)
function selectnextrecord(){
nextrecord = mylocalvariable.find(x=>!x.data().done)
console.log(nextrecord)
//expected: Get something different than the current record
//observed: This is being run with old data, so it returns the same record that I currently have with the old data.
}
let nextrecord;
selectnextrecord();
function submitchanges(){
let sfDocRef = db.collection('/mycollection').doc(nextrecord.id);
return db.runTransaction(function(transaction) {
return transaction.get(sfDocRef).then(function(sfDoc) {
if (!sfDoc.exists) {
throw "Document does not exist!";
}
transaction.update(sfDocRef, {done:true});
});
}).then(function() {
selectnextrecord();
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
}```
After going through the documentation, I think this is expected behavior.
Do not modify application state inside of your transaction functions. Doing so will introduce concurrency issues, because transaction functions can run multiple times and are not guaranteed to run on the UI thread. Instead, pass information you need out of your transaction functions
In any case, you could filter the documents that are not done with .where() and then place your transaction inside a foreach:
db.collection('cities')
.where("done", "==", true)
.get()
.then(snapshot => {
snapshot.forEach(doc => {
return db.runTransaction(function(transaction) {
return transaction.get(sfDocRef).then(function(sfDoc) {
if (!sfDoc.exists) {
throw "Document does not exist!";
}
transaction.update(sfDocRef, {done:true});
});
}).catch(function(error) {
console.log("Transaction failed: ", error);
});
})
})

Displaying MongoDB data in HTML table is adding blank rows

The mongoDB data I am displaying is information i scraped from a website using cheerio. I scrape the data, save it into a mongo collection (called Store), and then display that information in an HTML table using ejs.
Problem:
The first table displays information just fine, with 26 rows of data. The second table, however, displays 26 blank rows and then 25 rows of the data i scraped. Sometimes the roles will be reversed, just depending on which scrape occurs first, so I know it has something to do with when it gets put into the db.
Can someone please explain how I can fix this?
Code:
scrape function (function is exactly the same for second set of data but instead of SUP, it says QA):
var scrapeSUP = function() {
var SUPStoreInfo = [];
return Axios.get("http://example.com").then(function(response){
var $ = cheerio.load(response.data);
$('.row > tbody > tr:contains("SUP")').each(function(i, element){
let SUPResult = {
"environment.SUP": $(element).children().next(),
"store.SUP": $(element).children().next().next(),
"version.SUP": $(element).children().next().next().next()
};
SUPStoreInfo.push(SUPResult);
//make sure Store collection is empty
Store.count({}, function(err, count){
if (count === 0) {
//if empty, add newly scraped data
Store.create(SUPResult, function(err, new){
if (err){
console.log(err);
}
});
} else {
//if Store collection is not empty (has old data), remove all contents
Store.remove({}, function(err, doc) {
if (err) {
console.log(err);
} else {
//once all contents removed, add newly scraped data
Store.create(SUPResult, function(err, new){
if (err){
console.log(err);
}
});
}
})
}
});
});
return SUPStoreInfo;
});
}
please let me know if you need to see other code (html tables, mongoose schema, etc)

Overwrite object in mongodb

This should be simple but it is surprisingly difficult and extremely frustrating. I am trying to overwrite an 'Object' field in mongodb with a new Object that the user creates in my client webpage. I have validated that all other fields I am passing to the update operation are in fact being updated, with the exception of the javascript object. Instead of it updating with the object I am passing (While I validated is being populated with the object I am passing through), it just updates it back to {} instead of whats being passed:
{ nodes:[ { w: 120, h: 80,type: 'InHive',left: 184,top: 90,text: 'item',query: 'hey',name: 'sample',id: '7686132d-6fcf-4a3b-baa2-b1c628e0b2d6' } ], edges: [], ports: [],groups: [] }
When I attempt to update the data field outside of the meteor method, directly from the mongo console interface, it overwrites that field successfully with the javascript object. What am I doing wrong here, because I cant for the life of me figure this one out?
Server Method
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
MYCOLLECTION.update({
_id: id
}, {
$set: {
[field]: object, //this just gets reset back to {} whenever this update method is called
"metadata.last_modified_dt": new Date(), //this gets updated
"metadata.modified_by": Meteor.userId(), //this gets updated
'metadata.modified_by_username': _username //This gets updated
}
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
Client Call:
var _jsonformat = toolkit.exportData();
var currentid = Session.get('rulesRowClicked')._id;
console.log(_jsonformat);
Meteor.call('updateOneWorkflow' , currentid, 'data', _jsonformat, function(err, res){
if(err){
toastr.error('Failed to save result ' + err);
}
else{
toastr.success('Saved workflow');
}
});
I believe your problem is stemming from this line: [field]: object. I don't believe that's a proper method of dynamically accessing an object's field. Instead, try to dynamically update the field as so:
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
var newObj = {
"metadata": {
"last_modified_dt": new Date(),
"modified_by": Meteor.userId(),
"modified_by_username": _username
}
};
newObj[field] = object;
MYCOLLECTION.update({
_id: id
}, {
$set: newObj
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
The issue was crazier than I expected. If you are using Meteorjs and you are using the Aldeed Schema 2 collection framework, it seems to completely ignore updates/inserts of json objects even if you set the field type to Object, unless you set up the exact same schema as the object (including nested array objects) and attach it to your collection. Dumbest thing Ive ever seen, no idea why nothing warns you of this. I removed the schema attachment and it worked.

Meteor observeChanges(). How to check the actual changes?

I have a code that looks like this
Trades.find().observeChanges({
changed: function(id, fields) {
// do stuff
}
});
Where each Trades has an array of items inside
TradesSchema = new SimpleSchema({
// ...
items: {
type: [String]
},
// ...
});
Trades.attachSchema(TradesSchema);
These items are being changed sometimes, and I want to track the changes. The code works fine, except that in fields it returns all the items, not only the items that were changed.
Is there any way to see which exactly item was changed without changing the structure of the collection?
Thanks #Season for the hint!
observeChanges only gives the new values, so you have to use observe, since it returns both the new and old documents. Then you need to compare them to see what exactly got changed. (See docs for observe on meteor.com)
Trades.find().observe({
changed: function(newDocument, oldDocument) {
// compare newDocument to oldDocument to find out what has changed
}
});

How to find a document from mongodb using mongoose based on query and then insert some data to it and save back?

I have my Model as
var Model = {"name":String,"email":String,"notes":[{"time":Date,"title":String,"description":String}]
And I want to find document based on the email, and then add a note to the array. And then save it back.
What I tried is,
var updatedNote = {};
Model.findOne({'email':'test#test.com'},function(err, note){
for(var property in note._doc){
if(note._doc.hasOwnProperty(property)){
updatedNote[property] = note._doc[property];
};
}
updatedNote.notes.push(newNote);
note._doc = updatedNote;
note.save(function(err){
if(err){
console.log(error);
}
else {
res.redirect('/notes');
}
})
});
But it is throwing error as "Object does not have save method". I don't want to use findByIdAndUpdate() as i am leaving this responsibility of generating id on mongo.
I don't understand what most of that code is doing. If I wanted to add a note to the document (I'm assuming newNote is defined elsewhere), I'd just do:
Model.findOne({'email':'test#test.com'},function(err, note){
note.notes.push(newNote);
note.save(function(err){});
});