Mongoose Init Arrays with empty array instead of undefined - arrays

After some debugging, I came up with this code:
var trackSchema = new mongoose.Schema({
title: String,
playedAtTimestamps: Array
});
trackSchema.post('init', function(track) {
track.playedAtTimestamps = track.playedAtTimestamps || [];
});
So that anywhere else in the code, I know track.playedAtTimestamps is an Array. But I have the feeling my post-init callback is redundant to my Schema definition.
Is there a better practice? Should we somehow modify Mongoose's behavior?
Thanks

Gotcha :facepalm
I was doing
Track.findOne({})
.select('title') // Here is the mistake, I was not fetching playedAtTimestamps
.exec(function(err, track){
console.log(track);
track.incCounterSync((new Date()).getTime()); // Here is the error
track.save(function(err, track){
console.log(track);
});
});

Related

Angularjs get value from DynamoDB

I'm trying to get value from DynamoDB then assign the value to ng-model to display the value. However, the data is always null.
Dynamodb table
"meta_value": {
"clause_note": "Note: good job!",
"show_clause_note": true,
"shown": true
},
I'm getting the clause_note
Controller
$scope.clause_note = null;
$scope.item.remark = null;
$scope.loading = true;
$scope.getSettings = function () {
customPrint.getAllSettings($scope.module).then(function (res) {
if ($scope.module) {
settings.then(function (stt) {
$scope.clause_note = stt['clause_note'];
});
} else {
alert('No module is specified!');
}
}).finally(function () {
if ($scope.item.remark === $scope.clause_note) {
$scope.item.remark = '';
console.log($scope.clause_note);
}
else
{
$scope.clause_note = {show_clause_note: true};
$scope.clause_note = {shown: true};
}
});
};
$scope.getSettings();
The console log returned as null.
html
<ng-quill-editor ng-model="item.remark"></ng-quill-editor>
There isn't really enough information to answer this question. What is the value of the stt variable? If meta_value is a property on that object then this line:
$scope.clause_note = stt['clause_note'];
should be changed to
$scope.clause_note = stt.meta_value.clause_note
I'll edit this answer if you can let me know :)
But there are other problems with the code that make it harder to maintain.
For instance, it seems that $scope.clause_note can be a string or an object. That makes it harder to work with in other parts of the code because it's not always obvious what type it is.
The settings promise seems to come from nowhere. Maybe it would be a good idea to show where that comes from in your question. Also the response from getAllSettings is not used here. Is that a mistake?
Perhaps you should check if $scope.module exists before you even send the getAllSettings request. If it doesn't alert, and return. That should remove any branching logic inside your promise callbacks.

Jaydata saveChanges() counts tracked / changed entities, but doesn't send a batch request (with OData v4 Provider and Web Api)

by working with jaydata i am adding entities to a tree structure with deep nesting of entity-objects.
I attach the upper entity to the context and edit/add/remove related child entities. At the end i use saveChanges() with a promise.
The count-value passed to the promise tells that all changed entities have been counted correctly but saveChanges() didn't execute a batch request, persisting these entities.
So it feels like nothing else happens, but counting entities.
I post a small code example. I am quite sure, that the references of the entites are set correctly. (Working with jaydata, odata v4, web api and angularjs)
Is someone else having this problem with jaydata and found the reason?
Thanks for your help. =)
Greetings Paul
// Attach upper entity
DataService.jaydata.attach(viewModel.currentSkillTree.entity);
// Generating new entities
var newSkill = new DataService.jaydata.Skills.elementType({
Id: undefined,
Name: 'New skill',
Levels: [],
IconId: 47,
SkillTreeUsage: []
});
var newSkillLevel = new DataService.jaydata.SkillLevels.elementType({
Id: undefined,
ShortTitle: 'New level',
Skill: newSkill,
SkillId: undefined,
Level: 1,
RequirementSets: []
});
var newRequirementSet = new DataService.jaydata.RequirementSets.elementType({
Id: undefined,
SkillLevel: newSkillLevel,
SkillLevelId: undefined,
SkillTree: undefined,
SkillTreeId: viewModel.currentSkillTree.entity.Id,
});
var newSkillTreeElement = new DataService.jaydata.SkillTreeElements.elementType({
Id: undefined,
SkillTree: undefined,
SkillTreeId: viewModel.currentSkillTree.entity.Id,
Skill: newSkill,
SkillId: undefined,
Position: { X: x, Y: y }
});
// Completing object-references
viewModel.currentSkillTree.entity.Elements.push(newSkillTreeElement);
newSkill.Levels.push(newSkillLevel);
newSkill.SkillTreeUsage.push(newSkillTreeElement)
newSkillLevel.RequirementSets.push(newRequirementSet);
// Saving
DataService.jaydata.saveChanges()
.then(function (cnt) {
console.log('Saved entities:', cnt);
// The cnt-result in console is 4
// But no request was executed, nothing was saved
}, function (exception) {
console.log(exception); // Also no exception was thrown
});
So to not be that unkind.
The solution to solve the problem above to me, since i tried nearly every combination with entities (adding, attaching, .save(), .saveChanges(), object-references etc, figuring out it doesn't make sense anyway, it just acted the same way and seems to be so buggy), ended up within a workaround acting with classic nested async calls.
The solution was to save entities seperately within nested promises and to turn off the batch behavior of jaydata, to avoid double requests.
You can find the option within $data.defaults
$data.defaults.OData.disableBatch = true;
As result i am dealing now with good old nasty pyramids of doom, which at least gave the possibility back to save entities in the right order, with full control, the way the api needs it.
// Saving new SkillLevelRequirement connection
if (isConnectionGiven === false) {
// The first level of source skill where the target-skill-requirement will be added
var sourceSkillLevel = Enumerable
.From(sourceSkill.Levels)
.FirstOrDefault(null, function (x) {
return x.Level === 1;
});
// The last level of the target-skill to solve
var targetSkillLevel = Enumerable
.From(targetSkill.Levels)
.FirstOrDefault(null, function (x) {
return x.Level === targetSkill.Levels.length;
});
// First set of first level from source skill (will be used to add skilllevel-requirement)
var firstRequirementSet = sourceSkillLevel.RequirementSets[0];
// New RequirementAsignment
var newRequirementAssignment = new DataService.jaydata.RequirementAssignments.elementType({
RequirementSetId: firstRequirementSet.Id,
Order: 1
});
// New Requirement
var newRequirement = new DataService.jaydata.Requirements.elementType({
Title: requirementTypes.SKILL_CONNECTION,
RequirementOfIntId: undefined,
RequirementOfBoolId: undefined,
RequirementOfSkillLevelId: 0
});
// New RequirementOfSkillLevel
var newRequirementOfSkillLevel = new DataService.jaydata.RequirementsOfSkillLevel.elementType({
SkillLevelId: targetSkillLevel.Id,
});
// Loading symbol
showBusyIndicator();
newRequirementOfSkillLevel.save()
.then(function () {
newRequirement.RequirementOfSkillLevelId = newRequirementOfSkillLevel.Id;
newRequirement.save()
.then(function () {
newRequirementAssignment.RequirementId = newRequirement.Id;
newRequirementAssignment.save()
.then(function () {
// Loading symbol will be closed after tree reloaded
reloadCurrentTree();
}, function (exception) {
showJayDataExceptionModal(exception);
});
}, function (exception) {
showJayDataExceptionModal(exception);
});
}, function (exception) {
showJayDataExceptionModal(exception);
});
}
}
#jaydata developers: Thanks for 42 new grey hairs. I'm still at the point where i think i am using your tool wrong and jaydata could do so much better. Better up your documentation, sieriously. No desserts for you today.

Get form array data from Busboy

How do I get array form data using busboy?
In route:
req.busboy.on('field', function(fieldname, val){
//fieldname is string, expecting array
//'bunnies[gray]', etc...
});
And my view:
form(method="post" action="/post/path" enctype="multipart/form-data")
input(name="bunnies[gray]")
input(name="bunnies[white]")
input(name="bunnies[black]")
input(name="bunnies[brown]")
input(name="bunnies[purple]")
So busboy isn't stupid -- multipart/form-data does not by default support arrays in the same way as a JSON body does.
Requests with arrayName[n] as field names will not be parsed as arrays by busboy alone -- such a payload will have still have to be parsed manually.
One can manually parse these array values using one of these other answers...
... but if manually parsing arrays is undesired, one may consider using co-busboy instead using this option:
autoFields: true
The question is rather old, but in case someone else stumbles upon this problem, here's what I did:
var arr = new Array();
req.pipe(req.busboy);
req.busboy.on('field', function(key, value) {
if(key === 'array_name[]') {
arr.push(value);
}
});
req.busboy.on('finish', function() {
console.log(arr);
});
Question if 5 years old but it gave me a hint. I am coming from PHP background and didn't realize that Busboy is this stupid, so if you want to process array of fields, you need to actually process them like this:
busboy.on('field', (fieldname, val) => {
if (fieldname.indexOf('[]') !== -1) {
let fn = fieldname.replace('[]', '');
if (typeof req.body[fn] === 'undefined') {
req.body[fn] = [];
}
req.body[fn].push(val);
} else {
req.body[fieldname] = val;
}
});
Hope to save someone else a few hours of debugging ...

How to update an object's property which itself is an array objects in angular (mongoose)

This is a part of my schema:
var IdeaSchema = new Schema({
ratings: [{rater: String, star: Number}]
And i am trying to add a rating to the ratings array like this:
$http.put('/api/ideas/' + idea._id, {ratings: [{rater: 'John', star: 5}] });
After the first put, the newer ratings overwrite the array, and i always have the latest rating in it. I tried the suggested extend (this is the main issue i think) instead of merge but it does not seem to work.. I am not sure if i call the api with the correct syntax at all regarding the parameter ratings. And my update method is the yeoman (generator-angular-fullstack) generated one:
exports.update = function(req, res) {
...
var updated = _.merge(idea, req.body);
updated.save(function (err) {
..
return res.json(200, idea);
});
Edit:
I have made it by changing the api with this one:
$http.put('/api/ideas/' + idea._id + '/ratings', {rater: 'John', star: 5} );
I can now tell exactly what i want to update. So it is the ratings array of my idea. And a new method in controller:
router.put('/:id/ratings', auth.isAuthenticated(), controller.addRating);
exports.addRating = function(req, res) {
...
idea.ratings.push(req.body);
idea.save(function (err) {
...
});
};
I am suspicious if this would be the best approach to achieve this anyway. Maybe a better api or a better function would handle this with the generated classic update method.
I'll do something like this.
return Promise.cast(Idea.findOne({_id: idea._id, 'ratings.rater': rating.name}).exec())
.then(function(d){
if (d) {
return Promise.cast(Idea.update({_id: idea._id, 'ratings.rater': rating.name}, {$set : {'ratings.$' : rating}}).exec());
} else {
return Promise.cast(Idea.update({_id: idea._id, 'ratings.rater': {$nin : [rating.name]}}, {$push : {ratings : rating}}).exec());
}
});
So it will search if John's rating is already in there and do $push or $set correspondingly.

Remove a value from Firebase Array

I have a array in firebase created using the push() function.
I am trying to remove a specific value in that array.
var arr = $firebaseArray(ref.child('invoices').child('pending').child(coId));
arr.$loaded().then(function(){
var index = arr.$getRecord(invoiceId);
arr.$remove(index);
})
However, this is not working. I keep getting -1 for the var index. If there is an easier way to remove a value, with or without angularFire, I would be open to it.
Thanks!
I made a plunker for your case and it works:
var ref = new Firebase('https://benjaminsuch.firebaseio-demo.com/'),
arr = $firebaseArray(ref.child('invoices'));
arr.$loaded().then(function() {
var index = arr.$getRecord('item123423');
console.log('index', index);
arr
.$remove(index)
.then(function() {
console.log('item removed')
})
.catch(function(error) {
console.log('error', error);
});
});
Maybe you provide us a plunker too with your code, so we can see whats going on.

Resources