Backbone Ajax request with array of json data - node.js

I'm making a REST api for NodeJS with MongoDB that's using Backbone on the front end. This is the demo model
var MenuItem = Backbone.Model.extend({
idAttribute: "_id",
urlRoot: '/sentences'
});
This is the view code that calls fetch on that model (note I don't show the creation of that model in this code). I've hardcoded the _id for one of the mongo documents
itemDetails: function (event){
this.menuItemModel.set('_id', '526c0e21977a67d6966dc763');
this.menuItemModel.fetch();
The url that's generated for the post is this when menuItem.fetch() is called
XHR finished loading: "http://localhost:8080/sentences/526c0e21977a67d6966dc763".
Below is the json data at localhost:8080/sentences, so the xhr request to the url with the Mongo object id returns nothing. If I do localhost:8080/sentences/1, however, it returns the first from the array of json data.
[
{
"_id": "526c0e21977a67d6966dc763",
"question": "1",
"uk": "I heard a bloke on the train say that tomorrow's trains will be delayed.",
"us": "I heard a guy on the train say that tomorrow's trains will be delayed."
},
{
"_id": "526c0e21977a67d6966dc764",
"question": "2",
"uk": "Tom went outside for a fag. I think he smokes too much!",
"us": "Tom went outside for a cigarette. I think he smokes too much!"
},
{
"_id": "526c0e21977a67d6966dc765",
"question": "3",
"uk": "Do you fancy going to the cinema on Friday?",
"us": "How about going to the movies on Friday"
}
]
Question: Why isn't Backbone automagically returning the record when I call fetch on the model?
Update
this is the node.js method/route in server.js that returns the sentences
app.get('/sentences', function (req, res){
db.collection('english', function(err, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
});
});
})
Update
this is the function that searches for an individual record. It used to search by question (at which time /sentences/1 returned a record) but now that I've changed it to search by _id, this url (with the mongo id) is still not working "http://localhost:8080/sentences/526c0e21977a67d6966dc763"
app.get('/sentences/:id', function(req,res){
var query = { '_id' : req.params.id };
db.collection('english').findOne(query, function(err, doc) {
if(err) throw err;
console.dir(doc);
res.send(doc);
});
});

Related

Add new array element to JSON object in Node-Postgres

I have a json field in a postgres database that looks something like this :
{
"first_name": "John",
"last_name": "Doe",
"email": "johndoe#example.org",
"reviews" :[
{
"comment": "John gave us great service! Love this guy!",
"last_name": "Mariana",
"first_name": "Brown"
}
]
}
Using node, I'm trying to add a new array element (a new review) to the reviews. I want to be able to do this dynamically. The query I'm using ads in a array at index 2. That is not dynamic. I did find helpful material here but all the answers don't tell you how to update(add) to second level keys like the one in my situation. How can I do this?
Query
var text ="UPDATE users SET info = JSONB_SET(info, '{reviews,2}', '"+review+"') WHERE id=$1 RETURNING*";//works but not dynamic
var values = [userid];
pool.query(text, values, (err, res) => {
if (err) {
//log errors
console.log(err.stack);
//return error
io.to(socketid).emit('review-sent',{valid:'false'});
} else {
//success
console.log(res.rows );
var json = res.rows;
//success
io.to(socketid).emit('review-sent',{valid:'true'});
}
});
You can use jsonb_insert() if that is given a negative index it counts from the end. Passing true as the third parameter will then insert the new value after that, so jsonb_insert(..., '{reviews, -1}', true) will append the new value at the end:
update users
set info = jsonb_insert(info,
'{reviews,-1}',
'{"comment": "...", "last_name": "...", "first_name": "..."}',
true)
where id = 1;

UpdateOne Not Modifying Subdocument in MongoDB

I have a mongodb document structure that looks like this:
Document Structure:
{
"_id": ObjectID(59628aa0a6f87f2b68a4636a),
"name": "persons name",
"username": "persons username",
"password": "hashed password",
"formulas": [
{
"f_id": ObjectID(596bfdd758296f208859b9a8),
"name": "formula name",
"amount": "500",
"description": "a description",
"ingredients": [{...}, {...},...,]
}
]
}
I have a page in my express app that allows people to update the information in a formula that's stored inside the formulas array.
When I submit a post request to update the modified sub-document nothing is changed within the collection.
The code for this functionality is here, in NodeJS:
SAMPLE CODE:
router.post('/formula-list/:id', function(req, res){
var db = req.db.collection('users');
var f_id = new ObjectID(req.params.id);
var id = new ObjectID(req.user.id);
var formula = data;
db.updateOne({"_id": id, "formulas.f_id": f_id}, { $set: {
"formulas.$.name": req.body.name,
"formulas.$.description": req.body.description,
"formulas.$.formula": formula
}}, function(err, r){
assert.equal(null, err);
assert.equal(1, r.matchedCount);
assert.equal(1, r.modifiedCount);
req.db.close();
});
data.length = 0;
});
What I'm trying to do is grab the subdocument by its f_id so I can change the information for that particular subdocument, but this is apparently not working.
EDIT:
I realized my original issue is that my POST request wasn't actually hitting my server due to an AJAX request that I changed, but the issue now is that this query does not update the intended sub-document.
Per comment requests I've added in actual values for ObjectID_id and f_id fields.
I've also done a db.collection.find({}) command with both of the values used inside the snippet here and it correctly returned the document.

$pull not removing document from an Array in MongoDB

I have a MongoDB document that looks like this:
"_id": ObjectID(48kf4kblahblahblah),
"name": "A Person's Name",
"username": "apersonsemail#mail.com",
"password": "a hashed password",
"formulas": [
{
"f_id": ObjectID(4k8s9blahblahblah),
"name": "A Name",
"description": "A description",
"ingredients": [{object}, {object}]
}
]
}
I'm trying to query for a document based on _id and then remove the sub-document from the formulas array based on an item's f_id value using $pull.
However, it's not updating anything.
This is taking part in an Express/Node application, and my code looks like this:
router.delete('/formula-list/:index', function(req, res){
var db = req.db.collection('users');
var index = req.params.index;
db.updateOne({"_id": new ObjectID(req.user.id)}, { $pull: {"formulas": {"f_id": index}} }, function(err, r){
assert.equal(null, err);
assert.equal(1, r.modifiedCount);
req.db.close();
});
res.end();
});
And I get Assertion Error: 1 == 0
I've consoled req.params.index and I get the value
59683b480986823e10f39fba
And if I console the r object the matchedCount is 1, so I know it's finding the document as well. It's just not doing anything with it.
My questions seems very similar to this one, with the exception that I'm not looking to delete multiple items, but I don't see how this would affect the results of my query.
Thank you.

How to add to array in MongoDB document with mongoose?

I've got a collection of spellbooks in a mongodb. One of my API calls in express through mongoose is a PUT where the user provides the ID of the document and then a body that contains an array of spells. I want to update the array of spells in the spellbook document with the array brought in from the client.
Here's what the document looks like:
{
"_id": {
"$oid": "56f999342c2bdee43869c33b"
},
"name": "malagar22",
"username": "zak",
"spells": [
"56bd4da932c3b8e88e3c113a",
"56bd4da932c3b8e88e3c113b"
],
"__v": 0
}
Here's what my API call looks like:
app.put('/api/spellbook/:id', function (req, res) {
Spellbook.findById(req.params.id, function(err,spellbook) {
if (err) {
res.json({info:'error during find spellbook',error:err});
};
if (spellbook) {
_.merge(spellbook, req.body);
spellbook.save(function(err) {
if (err) {
res.json({info:'error updating spellbook',error:err});
};
res.json({info:'spellbook updated successfully'});
});
} else {
res.json({info:'spell not found'});
}
})
});
As you can see, I'm finding the spellbook that matches the ID. Then I'm doing a lodash merge with the request body, which I imagine would match the spells array in the document with the spells array in the body, which I'll post below. Then we update.
Here's my request:
{
"spells":[
"56bd4daa32c3b8e88e3c1148"
]
}
I'm getting the success callback, but when I check the database, the document isn't being updated. Sorry if this is really simple. I'm an MS SQL guy and this is my first time using Express and Mongo.

Updating mongodb and rendering it

I am learning mongodb, node.js and mongoose and want to update a mongodb and then display it on my browser. However my code only displays the results prior to my update even though I know the database has already been updated.
So for example I have two students called John and Tom, but when I update it with a third student called Fred and try to render the results, it only gives me John and Tom's details. Here is my code:
create: function(req, res) {
console.log('creating model');
var newStud = new Models.Student({
surname: req.body.surname,
firstname: req.body.firstname,
}
);
console.log('saving model');
newStud.save();
console.log('rendering model');
Models.Student.find({},
function(err,result){
console.log('finding results');
if (err) {
throw err;}
else {
console.log('returning results');
res.send(result);
}
}
);
},
When I update it with Fred's details, the console outputs the following:
creating model
saving model
rendering model
finding results
returning results
POST /students 200 21.629 ms - 5195
but the page only shows the following:
[
{
"surname": "Smith",
"firstname":"John"
"_id": "55bed36461521187445e5b53",
"__v": 0
},
{
"surname": "Peters",
"firstname":"Tom",
"_id": "55bed3f6c4faaa63464fc6df",
"__v": 0
},
]
I suspect my callback is not working properly. Can anyone explain why? Any help is most appreciated.
The problem here is of course that .save() is an asynchronous method in itself. So to need to wait for it to respond before asking for data from the collection. Otherwise, it likely has not actually created the new item yet:
create: function(req, res) {
console.log('creating model');
var newStud = new Models.Student({
surname: req.body.surname,
firstname: req.body.firstname,
}
);
console.log('saving model');
newStud.save(function(err,doc) { // <-- callback here
console.log('rendering model');
Models.Student.find({},
function(err,result){
if (err) {
throw err;}
else {
console.log('returning results');
res.send(result);
}
}
);
});
});
So basically you need to "wait" for the other .save() action to respond before you go query the whole collection to see the new addition.

Resources