Posting an array of objects to MongoDB with Node sends empty array - javascript

I am trying to POST an array of objects to my MongoDB database using NodeJS. When I post, all my fields show up empty. I put my code below, and below that explain what each of the console.logs output. Any ideas how to sort this out?
MODEL
var mongoose = require('mongoose');
var TransferSchema = new mongoose.Schema({
uploadDate: Date,
period: Number,
transferCode: String,
voucherNumber: String,
vendor: String,
description: String,
amount: Number
});
//convert schema to model
var Transfer = mongoose.model('Transfer', TransferSchema);
//export model for use elsewhere in app
module.exports = Transfer;
AJAX
- here I've tried posting both newArray and json. Both result in the same data posted to my db, but have a different effect on the console.logs in the controller file.
console.log(newArray);
json = JSON.stringify(newArray);
console.log(json);
$.ajax({
url: "http://localhost:3000/transfers/api",
type: "POST",
data: newArray,
datatype: 'json',
success: function(data, textStatus, jqXHR) {
console.log('posted!');
},
error: function(data, textStatus, errorThrown) {
console.log('failed');
}
})
transferController.js
-when posting newArray I get the following:
body: [object Object],
Body: {"undefined": ["", "", "", etc],
Text: undefined,
Done: undefined
-when posting json I get the following:
body: [object Object],
Body: {"{\"period\":5,\"uploadDate\":2015-11-19T21:00:00.000Z\",\"transferCode\":\"1041\",\"vendor\":\"Lakes State\",\"voucherNumber\":\"0000047571\",\"description\":\"1003-1555 Sal Tax Adj Gran Sep \",\"amount\":456802}...,
Text: undefined,
Done: undefined
//Create a new transfer
function createTransfer(request, response) {
console.log('posting');
console.log('body: ' + request.body); //TEST
console.info("Body: " + JSON.stringify(request.body)); //TEST
console.info("Text: " + JSON.stringify(request.body.text)); //TEST
console.info("Done: " + JSON.stringify(request.body.done)); //TEST
var transfer = new Transfer(request.body);
transfer.save(function(error) {
// console.log('transfer and transfer: ' + transfer);
if(error) return response.json({ message: 'could not create transfer because ' + error });
response.json({ transfer: transfer });
});
}
EDIT:
I tried using Insomnia to test what I'm sending. Weirdly, the below screenshot posts on Insomnia, but does not post in my app:
Also interesting, if I post several objects in an array using Insomnia, it does not work, as seen below:

Try setting contentType: 'application/json' in your ajax request and stringify your data like so JSON.stringify(newArray). This should ensure the data you are sending up is ok.
It looks like you are sending up many transfers but then trying to create one transfer from all the data (request.body)? You would need to loop over them and create them individually. Something like this:
request.body.forEach(function(obj) {
var transfer = new Transfer(obj);
transfer.save();
});

Related

Node.js/Express.js Ajax not returning string

I am trying to retrieve passwords in the database via the findOne method. Here is my Ajax:
$.ajax(
{
type: 'GET',
url: '/api/passwords/getPassword',
contentType: 'application/json',
dataType: "string",
async: true,
data: JSON.stringify({
"user_name": "fun.test.net",
"target": "Intern",
"system_type": "Test",
})
}).done(function(data)
{
window.ShowPassword(ele, data);
}).fail(function()
{
console.log("Error - Password Not Found.");
});
}
Along with its supporting function, which just swaps a button out for text (the password):
var buttonId = $(ele).attr('id');
var buttonText = $(this).html();
$('#' + buttonId).replaceWith("<span>" + "hello" + "</span>");
And here is my GET function:
router.get('/getPassword', async (req, res) =>
{
let passwords = await Password.findOne(
{
user_name: req.body.user_name,
target: req.body.target,
system_type: req.body.system_type,
});
if (!passwords) return res.status(404).send('Error 404: The password with the given ID was not found.');
res.send(JSON.stringify(passwords.password));
});
Whenever I call this function, it will throw the error:
TypeError: Cannot read property 'password' of null
at C:\Users\e0186030\Desktop\code\password_service2.0\routes\passwords.js:20:39
Please let me know what's going on! I'm not too familiar with Ajax, so I suspect that's what it is. But the idea is that the get function will return its password. It works in postman, so I know the call works by itself.
Try setting the JSON.stringify() to its own variable then sending it in the res:
const password = JSON.stringify(passwords.password);
res.send(password);
Your res.send() could be sending the password before it is actually stringified. Which would result in a null value. Hope this helps.

FormData array.push not working to send to Mongodb & Mongoose CastError: Cast to Array failed for value

I am completely lost to get some ajax form to work my case scenario I want to use a form to collect its data and post it to MongoDB using an Express App, for some reason I am trying to pass an array of sites to the DB but for some reason it's coming as a string with quotes but it won't accept an array of objects.
My Code:
$("#createClients").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
var siteArr = [];
$(".site").each(function(){
var siteUrl = $(this).val();
var siteObj = {
"site": siteUrl
};
siteArr.push(siteObj);// if I use stringify it returns 2 strings with 2 objects
});//building array of sites from inputs
console.log("Sites Array", siteArr);//Here the array looks right and returns all objects from the inteneration
formData.append('sites', siteArr);
// here I am appending it to the response but it returns like ["{"site":"site.com"},{"site":"site.com"}"]
// for some reason its generating quotes for the objects just like a string !!?!?!?
$.ajax({
url: "/clients/create",
type: "POST",
connection: "keep-alive",
cache: false,
contentType: false,
processData: false,
data: formData,
success: function (data) {
console.log(data);
},
error: function (err) {
console.log(err);
}
});
});// posts new Clients
My Mongoose model:
...
sites: [],
...
My problems:
The siteObj is returned from the formData() with quotes if I JSON.stringify the object sites:["{"site":"http://www.site1.com"},{"site":"http://www.site2.co.uk"}"].
If I pass the siteObj as a data type it returns sites:["[object Object],[object Object]"] as string.
What am I doing wrong here?... Thanks for your response in advance!
After doing some deeper research and another 3 days hammering my own head over this nonsense issue I came to a solution:
1. Mongoose validation can be done in 2 ways...
...
sites: [{site: {type: String}}], ... or using a new mongoose Schema
const SiteUrls = mongoose.Schema({
site: {type: String}
});
**then...**
sites: [SiteUrls]
...
2. The Ajax method to transfer FormData with appended Array should look like the example below or you will face a validation error from Mongoose "Cast to Array failed for value"...
$("#createClients").submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
var siteArr = [];
$(".site").each(function() {
var siteUrl = $(this).val();
siteArr.push({'site':siteUrl});
}); //building array of sites from inputs
console.log("Sites Array", JSON.stringify(siteArr));
formData.append('sites', JSON.stringify(siteArr));// SEND the array as string otherwise it will send [object object] as the string... this should build a response like [{"url":"site.com"},{"url":"site2.co.uk"}]... follow clients.js file use JSON.parse(req.body.sites); to turn it into a parsed object like so [{url:"site.com"},{url:"site2.co.uk"}]
$.ajax({
url: "/clients/create",
type: "POST",
connection: "keep-alive",
contentType: false,
cache: false,
processData: false,
data: formData,
success: function (data) {
console.log(data);
},
error: function(err) {
console.log(err);
}
});
}); // posts new Clients
THEN!!!
3. Clients.js Router
...
sites: JSON.parse(req.body.sites), // turn it into a parsable array so data is validated by mongoose and sent to DB
...
🎉🎉

Mongo Returns data with \n

I am using a form builder(https://github.com/kevinchappell/formBuilder). I have been able to store the generated JSON data(note that i am not sure if the data produced is in JSON form I am just storing it in a JS var) into my MongoDB. Here is where the data is coming from:
document.getElementById('getJSON').addEventListener('click', function() {
var ans = formBuilder.actions.getData('json', true);
$.ajax({
type: "POST",
dataType: "json",
data: ans,
url: "/j",
success: function(){
console.log('success');
}
});
document.forms["myForm"].submit();
});
It is generated here and sent as an AJAX call to the node server. The server then does the follows:
mongo.connect(url, function (err, db) {
assert.equal(null, err);
db.collection('clauses').insertOne(req.session.fdata, function (err, result) {
console.log('New Clause Added');
db.close();
});
});
It appears like so in the command prompt
the standard JSON format in which data appears in MongoDB
However when i fetch this data it comes as such:
[ { _id: 596de520ef77eb2614cd1e47,
'[\n\t{\n\t\t"type": "number",\n\t\t"label": "Number",\n\t\t"description":
"total number",\n\t\t"placeholder": "0",\n\t\t"className": "form-
control",\n\t\t"name": "number-1500374279764"\n\t}\n]': '' },
{ _id: 596de520ef77eb2614cd1e48 } ]
Am I passing the data in the wrong form? Or is the inserted data not in JSON in the first place? I am new to working with JSON and NOSQL databases.

Parsing a JSON Object with multiple Sub-Objects

<script type="text/javascript" src="http://static.stackmob.com/js/2.5.3-crypto-sha1-hmac.js"></script>
<script type="text/javascript">
$j.ajax({
dataType : 'json',
url : "/api/core/v2/groups/", //or any other rest call here
beforeSend: function(xhr) {
var bytes = Crypto.charenc.Binary.stringToBytes('username' + ":" + 'password');
var base64 = Crypto.util.bytesToBase64(bytes);
xhr.setRequestHeader("Authentication", "Basic " + base64);
},
success: function(data, status, xhr) {
console.log("success!");
console.log(data);
console.log(data[0]);
}
});
The output of data is
Object
data: Array[25]
0: Object
contentTypes: Array[4]
creationDate: "2012-05-31T20:21:20.532+0000"
creator: Object
description: "A discussion group for anyone interested in amateur radio."
displayName: "amd-amateur-radio-forum"
followerCount: 5
groupType: "OPEN"
id: 1133
memberCount: 3
modificationDate: "2012-06-04T21:23:07.078+0000"
name: "AMD Amateur Radio Forum"
resources: Object
type: "group"
viewCount: 62
__proto__: Object
1: Object
2: Object
3: Object
but when I try to output data[0] or data[1] they all come back as undefined.
I am not sure how to deal with this JSON object.
The output of alert(data) is
[Object object]
so I am assuming it is a properly formatted JSON object.
Here is the output JSON.stringify(data)
{"data":[{"contentTypes":["discussions","documents","blog","projects"],"memberCount":3,"creator":{"name":"firstname lastname","level":{"name":"Level I","description":"null","points":7,"resources":{"image":{"ref":"http://connect-dev.amd.com/api/core/v2/images/status/statusicon-47.gif","allowed":["GET"]}}},"username":"dkyle","email":"david.kyle#amd.com","firstName":"firstname","lastName":"lastname","resources":{"self":{"ref":"http://connect-dev.amd.com/api/core/v2/users/4183","allowed":["GET"]},"avatar":{"ref":"http://connect-dev.amd.com/api/core/v2/users/4183/avatar","allowed":["GET"]}},"id":4183},"groupType":"OPEN","name":"AMD Amateur Radio Forum","displayName":"amd-amateur-radio-forum","description":"A discussion group for anyone interested in amateur radio.","followerCount":5,"resources":{"projects":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133/projects","allowed":["GET"]},"invites":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133/invites","allowed":["POST"]},"documents":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133/documents","allowed":["GET","POST"]},"html":{"ref":"http://connect-dev.amd.com/groups/amd-amateur-radio-forum","allowed":["GET"]},"self":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133","allowed":["GET"]},"blog":{"ref":"http://connect-dev.amd.com/api/core/v2/blogs/1368","allowed":["GET"]},"members":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133/members","allowed":["GET"]},"discussions":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1133/discussions","allowed":["GET","POST"]}},"id":1133,"type":"group","creationDate":"2012-05-31T20:21:20.532+0000","modificationDate":"2012-06-04T21:23:07.078+0000","viewCount":62},{"contentTypes":["discussions","documents","blog","projects"],"memberCount":34,"creator":{"name":"firstname lastname","level":{"name":"Level I","description":"null","points":24,"resources":{"image":{"ref":"http://connect-dev.amd.com/api/core/v2/images/status/statusicon-47.gif","allowed":["GET"]}}},"username":"username","email":"kristi.fontenot#amd.com","firstName":"firstname","lastName":"lastname","resources":{"self":{"ref":"http://connect-dev.amd.com/api/core/v2/users/4291","allowed":["GET"]},"avatar":{"ref":"http://connect-dev.amd.com/api/core/v2/users/4291/avatar","allowed":["GET"]}},"id":4291},"groupType":"OPEN","name":"AMD Community Corps Connect (Matching Gifts, GIVE and Volunteerism)","displayName":"amd-community-corps-connect-matching-gifts-give-and-volunteerism","description":"Through this community, employees are be able to support the causes they care about most in ways thev have never been able to before. Not only that, employees will be able to connect and network with fellow AMD employees in a way that allows everyone connected to each other to volunteer together, while providing the ability to track volunteer hours, make charitable contributions and request a match all in the same tool. \r\n\r\nhttp://amd.yourcause.com \r\n\r\n","followerCount":55,"resources":{"projects":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074/projects","allowed":["GET"]},"invites":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074/invites","allowed":["POST"]},"documents":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074/documents","allowed":["GET","POST"]},"html":{"ref":"http://connect-dev.amd.com/groups/amd-community-corps-connect-matching-gifts-give-and-volunteerism","allowed":["GET"]},"self":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074","allowed":["GET"]},"blog":{"ref":"http://connect-dev.amd.com/api/core/v2/blogs/1267","allowed":["GET"]},"members":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074/members","allowed":["GET"]},"discussions":{"ref":"http://connect-dev.amd.com/api/core/v2/groups/1074/discussions","allowed":["GET","POST"]}},"id":1074,"type":"group","creationDate":"2012-05-07T19:24:31.880+0000","modificationDate":"2012-09-07T02:00:51.821+0000","viewCount":544}
It is actually longer than that
If you are outputting stringifying data and you have inside that an array named data then you need to do data.data[0] instead of data[0].
It would be a little more clear for you if you said:
success: function(result, status, xhr){
var data = result.data;
Then data[0] would work just fine.

cakephp 2.2 retrieve json data in controller

I'm trying to send JSON data from a web page using JQuery, like this:
$.ajax({
type: "post", // Request method: post, get
url: "http://localhost/ajax/login",
data: '{username: "wiiNinja", password: "isAnub"}',
dataType: "json", // Expected response type
contentType: "application/json",
cache: false,
success: function(response, status) {
alert ("Success");
},
error: function(response, status) {
alert('Error! response=' + response + " status=" + status);
}
});
In cake2.2, I have a controller named Ajax that has a method named "login", like this:
public function login($id = null)
{
if ($this->RequestHandler->isAjax())
{
$this->layout = 'ajax'; // Or $this->RequestHandler->ajaxLayout, Only use for HTML
$this->autoLayout = false;
$this->autoRender = false;
$response = array('success' => false);
$data = $this->request->input(); // MY QUESTION IS WITH THIS LINE
debug($data, $showHTML = false, $showFrom = true);
}
return;
}
I just want to see if I'm passing in the correct data to the controller. If I use this line:
$data = $this->request->input();
I can see the debug printout:
{username: "wiiNinja", password: "isCool"}
I read in the CakePHP manual 2.x, under "Accessing XML or JSON data", it suggests this call to decode the data:
$data = $this->request->input('json_decode');
When I debug print $data, I get "null". What am I doing wrong? Is my data passed in from the Javascript incorrect? Or am I not calling the decode correctly?
Thanks for any suggestion.
============= My own Edit ========
Found my own mistake through experiments:
When posting through Javascript, instead of this line:
data: '{username: "wiiNinja", password: "isAnub"}',
Change it to:
data: '{"username": "wiiNinja", "password": "isAnub"}',
AND
In the controller code, change this line:
$data = $this->request->input('json_decode');
To:
$data = $this->request->input('json_decode', 'true');
It works.
Dunhamzzz,
When I followed your suggestions, and examine the "$this->request->params" array in my controller code, it contains the following:
array(
'plugin' => null,
'controller' => 'ajax',
'action' => 'login',
'named' => array(),
'pass' => array(),
'isAjax' => true
)
As you can see, the data that I'm looking for is not there. I've already got the the proper routes code. This is consistent with what the documentation for 2.x says here:
http://book.cakephp.org/2.0/en/controllers/request-response.html
So far, the only way that I found to make it work, is as stated above in "My own Edit". But if sending a JSon string to the server is not the right thing to do, I would like to fix this, because eventually, I will have to handle third party code that will send JSon objects.
The reason you are struggling wit the data is because you are sending a string with jQuery, not a proper javascript object (JSON).
$.ajax({
type: "post", // Request method: post, get
url: "http://localhost/ajax/login",
data: {username: "wiiNinja", password: "isAnub"}, // outer quotes removed
dataType: "json", // Expected response type
contentType: "application/json",
cache: false,
success: function(response, status) {
alert ("Success");
},
error: function(response, status) {
alert('Error! response=' + response + " status=" + status);
}
});
Now the data will be available as a PHP array in $this->request->params.
Also for sending a JSON response, please see this manual page. Most of your code there can be reduced to just 2 lines...
//routes.php
Router::parseExtensions('json');
//Controller that sends JSON
$this->set('_serialize', array('data'));

Categories

Resources