How do i store an array of objects with angularJS - javascript

i have this schema of a object in mongoDB, i will call my object CAR in this question:
this.carroSchema = new Schema({
modelo: String,
ano: String,
placa: String,
cor: String,
categoria: [{tipo: String, preco: String}],
createdOn: {type: Date, default: Date.now}
});
and i have this function that gets the object CAR and stores in the array 'arrayCarros'
$scope.carregarCarros = function(){
$http({
method: 'GET',
url: '/listaCarro'
})
.then(function successCallback(response){
$scope.arrayCarros = response.data;
}, function errorCallback(response){
alert(response.data);
});
}
if i do a select like this:
<select class="form-control" ng-click = "carregarCarros()" name="select">
<option ng-repeat = "carros in arrayCarros">{{carros.placa}}</option>
</select>
i have access to the propertie 'placa' from the object CAR, so i can show the values in my select.
but, my question is, how do i store the array 'categoria' that is inside of my object CAR, in other array so i can do a ng-repeat of him in my option and have access of his properties like 'tipo' and 'preco'?

Here is a simple way to do it. Obviously you could always use a built in javascript function like Array.filter or Array.reduce depending on your use case, but below is a simple to follow solution.
$scope.other_array = [];
response.data.forEach(function(car){
$scope.other_array.push(car.categoria)
})
console.log(other_array)
It should also be noted you can have multiple ng-repeats and just have one render carros.place and one render carros.categoria. That or just have both vars rendered within the same ng-repeat.

Related

In mongoose, how to find records based on value in related collection?

In Mongoose, I have two collections, with one referencing the other. Is it possible to have a find query that selects records based on a value in the other. An example of what I am try to get at (not actual schemas):
const CarModelSchema = new mongoose.Schema({
name: String,
brand: { type: mongoose.Schema.Types.ObjectId, ref: 'CarBrand' }
});
const CarBrandSchema = new mongoose.Schema({
name: String,
country: String
});
I then want to perform a query of the form, without needing to do two queries:
CarModelSchema.find({ 'brand.country': 'GER' });
So far I haven't been able to make this work, so I am wondering whether this can be done in Mongo or whether I am approaching it wrong?
Yes it is possible.
I realize you don't have models for your schemas so add them like this:
const CarModel = mongoose.model('CarModel', CarModelSchema);
const CarBrand = mongoose.model('CarBrand', CarBrandSchema);
Also brands should be defined like this:
brand: [{ type: mongoose.Schema.Types.ObjectId, ref: 'CarBrand' }] //added the brackets
You can then run a find query to filter by country by doing the following:
CarModel.
find(...).
populate({
path: 'brand',
match: { country: { $eq: 'GER' }},
// You can even select the field you want using select like below,
select: 'name -_id',
//Even limit the amount of documents returned in the array
options: { limit: 5 }
}).
exec();
And that should do it, as long as the ObjectIds saved in brands array in the CarModel collection are valid or exist.
Using match in your population will do the work.
CarModel.find()
.populate({
path: 'brand',
model: CarBrandModel,
match: { country: { $eq: 'GER' }},
})
.exec()
Keep in mind you have to define CarModel and CarBrandModel like this:
const CarModel = mongoose.model('CarModel', CarModelSchema)
const CarBrandModel = mongoose.model('CarBrandModel', CarBrandSchema)
Yes, you are doing it wrong.
In CarModelSchema.brand there is not string saved, there is ObjectId saved, therefore you have to find that ObjectId (the reference).
You can do it manually - first finding the CarBrandSchema.find({ 'country': 'GER' }); and then use its ObjectId (=_id), or you can use https://mongoosejs.com/docs/populate.html to populate your CarModel with the CarBrand object.

Accessing minimongo from template helper meteor / mongodb

I am trying to access my Products collection in Minimongo in the html page. When I am in my browser console, I am able to type Products.findOne(); and it will return a product.
However, when I try to return a product from my template helper, I get undefined. Thoughts anyone?
Template.Tires.onRendered(function() {
console.log(Products.findOne());
//after I return a product item, I need to modify its properties manually after it has loaded into the client
});
Simple answer:
Do whatever modification you need to do on the collection within the helper function and then return a JS object. For instance if you collection looks something like this:
SomeColleciton
_id
type: String
birthday:
type: Date
firstname:
type: String
lastname:
type: String
timezone:
type: Integer
you can do the following to transform it
Template.Tires.helpers({
user: function(userId) {
var u = SomeCollection.findOne(userId);
var age = calcAge(u.birthday);
var ifworkinghour = calcifworkinghour(u.timezone);
return {name: u.firstname + ' ' + u.lastname, age: age, workinghour: ifworkinghour}
});

Saving string when field is nested object

My Item Schema:
new Schema({
name: {
ka: String,
en: String
}
});
When doing like this:
Item.findOne({}, function(err, item){
item.name = 'wrongtype';
item.save();
});
item's name property is saved to database, despite of fact that name is described as object in schema. Validation is not working. Can you suggest solution? Or explain if it's correct behaviour

Why can't I modify my model's virtual attribute in my controller?

I have the following virtual attribute defined in my model.
var ObjectSchema = new Schema({
short_id: {
type: String,
required: true,
unique: true
},
created: {
type: Date,
default: Date.now
}
})
ObjectSchema.virtual('voted').get(function () {
return false;
})
I try to change it in my controller, yet it still remains unchanged, why is this?
Object.find({ short_id: req.params.shortId }).exec(function(err, objects) {
objects[0].voted = true;
res.jsonp(objects[0]);
});
The JSON still says object.voted = false
When you want to freely manipulate the results of a Mongoose query, you can use a lean() query which generates plain JavaScript objects instead of model instances:
Object.find({short_id: req.params.shortId}).lean().exec(function(err, objects) {
objects[0].voted = true;
res.jsonp(objects[0]);
});
You should convert all your Mongoose objects to plain JS objects with .toObject() before doing so:
Object.findOne({ short_id: req.params.shortId }).exec(function(err, doc) {
object = doc.toObject();
object.voted = true;
res.jsonp(object);
});
Or, if you don't need setters, getters, virtuals or any other of Mongoose magic to be applied to your documents, you may use lean queries (as JohnnyHK suggested):
Object.findOne({ short_id: req.params.shortId }).lean().exec(function(err, object) {
object.voted = true;
res.jsonp(object);
});
In this case you'll see all your documents exactly like they are stored in MongoDB. So, there will be no voted field despite your virtaul. There will be no .save() method either.

Recreate models using Mongoose

I want to recreate the models in database after dropping everything in it.
Mongoose (or Mongo itself )actually recreates the documents but not the indices. So is there a way to reset Mongoose so that it can recreate indices as if running the first time?
The reason why I'm using dropDatabase is because it seems easier while testing. Otherwise I would have to remove all collections one by one.
While not recommended for production use, depending on your scenario, you can add the index property to a field definition to specify you want an index created:
var animalSchema = new Schema({
name: String,
type: String,
tags: { type: [String], index: true } // field level
});
animalSchema.index({ name: 1, type: -1 }); // schema level
Or,
var s = new Schema({ name: { type: String, sparse: true })
Schema.path('name').index({ sparse: true });
Or, you can call ensureIndex on the Model (docs):
Animal.ensureIndexes(function (err) {
if (err) return handleError(err);
});

Categories