Rendering Mongo document values in Pug template w/ Express - javascript

I'm retrieving documents from Mongo Atlas using the new data API like this :
axios(config)
.then(function (response) {
console.log(response.data);
res.render('profile', {
snippets: response.data,
})
.catch(function (error) {
console.log(error);
});
};
My console.log(response.data) shows the documents correctly like this :
documents: [
{
_id: '6245b82edde6452fece5d27d',
snippet: '<p>This is a test post in <strong>bold, </strong>in <em>italic, </em>in <span style="text-decoration: underline;">underline,</span> and with a link</p>'
},
{
_id: '6245b8fbe9d255ab42528197',
snippet: '<p>This is a test post in <strong>bold, </strong>in <em>italic, </em>in <span style="text-decoration: underline;">underline,</span> and with a link. A second time!</p>'
}
]
}
Then I followed this answer to try render a simple list of these of the snippet values in a table :
table
each snippet in snippets
tr#snippet_list_item
td #{snippet._id}
td #{snippet.snippet}
But I get
snippets include [object Object],[object Object]
rendered on the front end instead of the values.
What am I missing? My thinking was... pass the objects, iterate through, access the values for each. But I'm obviously not doing something right.

Okay so for people coming to this whilst still learning...
If you ever get this problem, where you are trying to access values inside an array of objects and are getting 'Object Object', make sure to look at the structure of the data you are getting.
See below
documents: [
{
_id: '6245b82edde6452fece5d27d',
snippet: '<p>This is a test post in <strong>bold, </strong>in <em>italic, </em>in <span style="text-decoration: underline;">underline,</span> and with a link</p>'
},
{
_id: '6245b8fbe9d255ab42528197',
snippet: '<p>This is a test post in <strong>bold, </strong>in <em>italic, </em>in <span style="text-decoration: underline;">underline,</span> and with a link. A second time!</p>'
}
]
}
My data is structured like this :
'documents'[
{document 1}
{document 2}
]
Each {document} is an object. But they are all inside an array of objects, which in my case is 'documents'. You can see this by the [] square brackets that the {documents} are contained inside.
So when accessing the values, you first need to access the array by response.data.{$name_of_array}, THEN, you can use dot notation to access the values
so to access the values, you'd do something like :
response.data.{$name_of_array}.{$name_of_value_name}
if accessing all of these, you'll need to iterate through them, if accessing just 1, you can use it's position in the index like this :
response.data.{$name_of_array}[$index_number].{$name_of_value_name}
Hope this helps someone!

Related

How i can get query string from file to query database in expressjs?

I'm trying to use this code but it's not working
var content = fs.readFileSync('/home/diegonode/Desktop/ExpressCart-master/views/partials2/menu8xz.hbs', 'utf8' );
req.db.products.find( content ).skip(0).limit(3).exec(function (err, results) {
please anyone help me (this is a extract of code)
i put the rest of code
req.db.products.find( content ).skip(0).limit(3).exec(function (err, results) {
res.render('index', {
title: 'Shop',
results: results,
session: req.session,
message: clear_session_value(req.session, "message"),
message_type: clear_session_value(req.session, "message_type" , req.body.product_id),
config: req.config.get('application'),
helpers: req.handlebars.helpers,
page_url: req.config.get('application').base_url,
show_footer: "show_footer"
});
console.log(content );
});
console.log(content );
});
It looks like your mapper's find function expects a conditions object, and when you read content directly from the file it's a plain text string that just happens to look like an object instead.
You need to do two things: first, "quote" product_title to make the file valid JSON; and second, use JSON.parse to turn content into an object which db.products.find can work with.

Sequelize: .createAssociation() or .setAssociation doesn't update the original object with created data

I've been stuck on this for a while. Take the following code as an example:
models.Summoner.findOne({
include: [{ model: models.RankedStats, as: 'SummonerRankedStats', required: true }],
where: { summonerId: summonerId, server: server }
}).then(function(summoner) {
models.RankedStats.create({
totalWins: 0,
totalLosses: 0
}).then(function(rankedStats) {
summoner.setSummonerRankedStats(rankedStats).then(function() {
console.log(summoner.SummonerRankedStats)
//This outputs undefined
summoner.getSummonerRankedStats().then(function(srs) {
console.log(srs)
//This outputs the RankedStats that were just created
})
models.Summoner.findOne({
include: [{ model: models.RankedStats, as: 'SummonerRankedStats', required: true }],
where: { summonerId: summonerId, server: server }
}).then(function(summoner) {
console.log(summoner.SummonerRankedStats)
//This outputs the SummonerRankedStats object
})
})
})
})
So, to put it simply... If I have a Summoner (var summoner) and perform a .setAssociation() or .createAssociation() on it, and then log summoner, the data created isn't there. If I fetch it again from the database (with .getAssociation() or by searching for that Summoner again) I can access it, but I was hoping to avoid that extra DB call.
Is there a way to add this information to the original object when using .create() or .set()? It can be achieved by doing something like:
summoner.dataValues.SummonerRankedStats = rankedStats
But that seems somewhat hacky :)
Is there a correct way to do it, or does it even make any sense?
Thanks in advance!

AngularJS Nested Object Array Pathway

I have a factory, which goes into a controller, and I am trying to get data from that display on an HTML page. I am having trouble specifying an Object's pathway however.
My Factory:
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
apis:
[{
accounts: [
{
v1: [
{
uri: Head+"/v1/accounts/",
item1: "AccountNumber",
item2: "MoneyInAccount"
}],
v2: [
{
uri: Head+"/v2/accounts/",
item1: "AccountNumber",
item2: "MoneyInAccount"
}]
}
],
customers: [
{
v1: [
{
uri: Head+"/v1/customers/",
item1: "CustomerName",
item2: "CustomerID",
item3: "CustomerEmail"
}]
}
]
}]
};
});
My Controller:
app.controller('APIController', function($scope, APIMethodService) {
$scope.title = "API";
$scope.apiList = APIMethodService;
$scope.accountList = $scope.apiList.accounts.v1;
$scope.accountList2 = $scope.apiList[0][0];
});
My HTML
<div ng-controller="APIController">
<div id="api" class="row">
<div class="col-xs-12">
<div class="row" style="font-size:20px">
{{title}} Page!
<table class="table table-striped">
<tr ng-repeat="api in apiList | orderBy:'uri' | filter:search">
<td>{{api.uri}}</td>
<td>{{api.item1}}</td>
<td>{{api.item2}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
The errors I get are in regards to the Controller trying to parse out the individual objects I wish to grab, like accounts or customers, and then any version v#, they may have.
So it will say something such as
TypeError: Cannot read property 'v1' of undefined
I just need some help specifying the proper pathways into my factory service.
You have a few problems. First, you are referring to the object returned from the factory incorrectly. APIMethodService is the factory that you're injecting, so you need to first reference the object that that factory is returning like this:
APIMethodService.apis
This will give you your entire JSON object.
From there, the rest of your object is made up of arrays of objects, so referring to 'v1' won't do you any good. You need to specify an index instead. If you want v1, you'll need:
APIMethodService.apis[0].accounts[0].v1
This will give you the v1 array, which again is an array of objects.
Customers would be:
APIMethodService.apis[0].customers[0].v1
The first problem you have is that the factory returns an object with a single property called apis. So basically this $scope.apiList.accounts.v1 should be $scope.apiList.apis.accounts.v1. Bu that's not all as this won't either work since dotting(.) into apis is an array you'd have to use the index. In this case it would be $scope.apiList.apis[0] and then you could .accounts[0].v1 which is also an array containing a single object.
Now if you can I would suggest to you that you'd change how you represent this data structure.
This is how you could do it.
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
accounts: {
v1: {
uri: Head+"/v1/accounts/",
items: ["AccountNumber","MoneyInAccount"]
},
v2: {
... // skipped for brevity
}
},
customer: {
... // code skipped for brevity
}
};
});
And then it's just a matter of dotting into your APIMethodService-object like APIMethodService.accounts.v1.items[0] if you want the AccountNumber method name.
Constructing your url could then be done like this.
var baseUrl = APIMethodService.accounts.v1.uri; // 'api.example.com'
var url = baseUrl + APIMethodService.accounts.v1.items[0]; // 'AccountNumber'
// url = "api.example.com/v1/accounts/AccountNumber"
Again, this is one way you could do it but this can be further enhanced upon. The examples I provided are simply for demo purposes and this is not in any way the only way to do it.
Expanding upon recieved comments/questions your service (and data representation) could now look like this.
app.factory('APIMethodService', function() {
var Head = "api.example.com";
return {
accounts: {
v1: {
uri: Head+"/v1/accounts/",
items: [
{
name:'AccountNumber',
description:'Show the account number'
},
{
name:'AccountOwner',
description:'Show information about the owner of the account'
},
{
name:'MoneyInAccount',
description:'Show money in the Account'
}
]
},
v2: {
... // skipped for brevity
}
},
customer: {
... // code skipped for brevity
}
};
});
// Get descriptions
var accountNumberDescription = APIMethodService.accounts.v1.items[0].description; // 'Show the account number'
var accountOwnerDescription = APIMethodService.accounts.v1.items[1].description; // 'Show information about the owner of the account'
var moneyInAccountDescription = APIMethodService.accounts.v1.items[2].description; // 'Show money in the Account'
By using objects with properties like this it's alot easier to understand what you are trying to do. With arrays with indexes you'd have to know or take a look at the source to see what's going on. Here, someone viewing your code they can instantly understand that it is the description you are getting.

Expected response to contain an array but got an object

So I'm new in Angular, and I've looked over various other solutions, but no one seemed to work for me. My app needs to take some data from mongodb database and show it to the client. The thing is I get
Error: [$resource:badcfg] Error in resource configuration for action query. Expected response to contain an array but got an object
Here is my SchoolCtrl.js on the client
app.controller('SchoolsCtrl', function($scope, SchoolResource) {
$scope.schools = SchoolResource.query();
});
Here is my ngResource
app.factory('SchoolResource', function($resource) {
var SchoolResource = $resource('/api/schools/:id', {id: '#id'}, { update: {method: 'PUT', isArray: false}});
return SchoolResource;
});
This is my SchoolsController on the server
var School = require('mongoose').model('School');
module.exports.getAllSchools = function(req, res, next) {
School.find({}).exec(function(err, collection) {
if(err) {
console.log('Schools could not be loaded: ' + err);
}
res.send(collection);
})
};
I tried adding IsArray: true, tried adding [] after 'SchoolResource' in the resource, tried changing routes, nothing worked. I wanted to see what actually is returned, that the query complained is not array, so I turned it to string and this was the result:
function Resource(value) { shallowClearAndCopy(value || {}, this); }
I have no idea why it returns a function. Can anyone help me?
That error message usually means your server is returning JSON representing a single object, such as:
{"some": "object", "with": "properties"}
when Angular is expecting JSON representing an array, like:
[ {"some": "object", "with": "properties"}, {"another": "object", "with": "stuff"} ]
Even if there is only a single result, query expects JSON for an array:
[ {"a": "single", "result": "object"} ]
You can verify this by simply loading your API call into the browser and checking it out. If there aren't square brackets around the whole JSON response, it isn't an array.
It happened to me too, but then I printed the object in the console and found out that there was something like this:
{ options:{....},results:[ ...the Array I was looking for... ]}
so all you need to do there is
res.send(collection.results);
I hope this helps

How to add a new object to an array nested inside an object?

I'm trying to get a handle on using $resource in angularjs and I keep referencing this answer AngularJS $resource RESTful example for good examples. Fetching a record and creating a record work fine, but now i'm trying to add a "section" to an existing mongo record but can't figure it out.
documents collection
{
_id: 'theid',
name: 'My name",
sections: [
{
title: 'First title'
},
{
title: 'Second title'
}
]
}
angular controller snippet
var document = documentService.get({_id: 'theid'});
// TRYING TO ADD $scope.section TO THE SECTIONS ARRAY IN THE VARIABLE document.
//document.sections.push($scope.section); <-- This does NOT work
//document.new_section($scope.section); <-- could do this and then parse it out and insert it in my backend code, but this solution seems hacky and terrible to me.
document.$save(function(section) {
//$scope.document.push(section);
});
documentService
return $resource(SETTINGS.base + '/documents/:id', { id: '#id' },
{
update: { method: 'PUT' }
});
From the link i posted above, If I was just updating the name field, I could just do something like this:
var document = documentService.get({_id: 'theid'});
document.name = "My new name";
document.$save(function(section) {
//$scope.document.push(section);
});
I'm just trying to add an object to a nested array of objects.
Try this:
documentService.get({_id: 'theid'}, function(document) {
document.sections.push($scope.section);
document.$save();
});

Categories

Resources