How to fetch particular objects by their attribute from Array? - angularjs

I need to get objects with special attribute "type" out of Array. These objects I am going to assign to scope. How can I do this?
The following approach didn't work out for me.
$scope.vendors = {}
$scope.clients = {}
$scope.loadCounterparties = function() {
Counterpartie.query(function(response) {
$scope.vendors = response.type.Vendor;
$scope.clients = response.type.Client
});
};
Response objects look like this
Thanks in advance!

Angular doesn't have something dedicated for this. You need to filter the arrays via plain java script. However you can try using a 3rd party library by the name underscore.js.
It adds many usefull functions like "where":
_.where(list, properties)
Looks through each value in the list, returning an array of all the values that contain all of the key-value pairs listed in properties.
_.where(listOfPlays, {author: "Shakespeare", year: 1611});
=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
{title: "The Tempest", author: "Shakespeare", year: 1611}]
Here is a link to the library's page
http://underscorejs.org/#where

can use angular forEach but I would use lodash
// assuming one array and two search arguments i.e. client and vendor
var data = response;
$scope.loadCounterparties = _.filter(data, {type: 'Vendor', type: 'Client'});

Related

Why Can't I Use Template Literals to Create Strings as Keys In a New Object? 😕

I have some Array of Objects, with a sample Object as such:
{
id: 10,
name: "Clementina XYZ",
username: "Moriah.Stanton",
email: "foo.bar#quux.biz",
address: {
street: "Kattie Turnpike",
suite: "Suite 555",
city: "Lebsackbury",
zipcode: "31428-2261",
geo: {
lat: "-38.2386",
lng: "57.2232"
}
},
phone: "555-648-3804",
website: "example.com",
company: {
name: "Acme LLC",
catchPhrase: "Centralized empowering task-force",
bs: "target end-to-end models"
}
}
I also have a function that is working just fine to find users that work in the same company.name and map over them to create Objects with name, address and phone.
function buildCompanyDirectory(company, directory) {
return directory
.filter(user => user.company.name === company)
.map(({ name, address, phone }) => ({
name,
address,
phone
}));
}
Now, a new task:
// TODO: Build an Array of company directories
So, I expect to have a final Array consisting of 🔑s that are derived from user.company.name with values that are Arrays of Objects with 🔑s of name, address and phone. So, something like:
[{
"Hoeger LLC": [{ }]
}]
As part of solving this, I feel (evidently JS doesn't agree!) that I should be able to use template literals to create new objects using 🔑s that are derived from the values from another object.
That nonworking code looks like this:
const directories = users.map((user) => {
return {
`${user.company.name}` : buildCompanyDirectory(company.name, users) // ERROR: Property assignment expected
};
});
It doesn't seem that I should need to resort to Object.keys() or anything like that. This feels more like some type of 'syntax' error or just bad notation.
Naturally, I would like to know the simplest way to get this working out! Thanks.
The problem is that key construction in object literals is special-cased in JS. You can use either a literal string or a bare identifier.
To allow an expression as a key in an object literal, JS uses the following hack:
const a = 'aaaa';
const data = {[`this_is_${a}`]: 10}
data.this_is_aaaa === 10; // true.
The expression within [] will be evaluated and used as a key.

Pushing onto Mongo SubDoc of SubDoc array

I'm going around in circles with this one so hoping someone can help. I'm building a nodejs application that receives sensor values from nodes. There can be multiple sensors on a node.
Using NodeJS, Mongod DB and Mongoose, all running on a raspberry pi, 3 I've built the following Schemas & Model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var valueSchema = new Schema ({
timestamp: {type: Date},
value: {}
});
var sensorSchema = new Schema ({
id: {type: Number},
type: {type: String},
description: {type: String},
ack: {type: Boolean},
values: [valueSchema]
});
var SensorNode = mongoose.model('SensorNode', {
id: {type: Number, required: true},
protocol: {},
sensors: [sensorSchema]
});
I can add in the node, and push sensors onto the sensors array, but I seem unable to push values onto the values array.
I've looked over a few other examples and questions on similar issues, and looked at using populate, but cant seem to get them to work.
Here is my code:
function saveValue(rsender, rsensor, payload) {
var value = {
values: {
timestamp: new Date().getTime(),
value: payload
}
}
SensorNode.findOneAndUpdate({
"id": rsender,
"sensors.id": rsensor
}, {
"$push": {
"sensors.$": value
}
}, function(err, result) {
if (err) {
console.log(err);
}
console.log(result);
});
}
This is returning undefined for the result and this error:
MongoError: exception: Cannot apply $push/$pushAll modifier to non-array
Values is definitely an array in the sensor schema.
I'm using readable ids rather than the auto assigned Mongo DB IDs for the sake of the UI, but I could use the MongoDB _id if that makes any difference, I don't see why it would?
Where am I going wrong ?
You're using positional operator $ so let's check the docs
The positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array. To project, or return, an array element from a read operation, see the $ projection operator.
So sensors.$ will return one particular document from your sensors array. That's why you're getting an error. On this level of your document you can only replace this item by using $set. I bet you wanted to do something like this:
SensorNode.findOneAndUpdate({
"id": rsender,
"sensors.id": rsensor
}, {
"$push": {
"sensors.$.values": payload
}
});
This operation will just append payload to values array in one particular sensor with id equal to rsensor.

mongoose query: find an object by id in an array

How could I find an image by id in this Schema. I have the id of the User and the id of the image I am looking for. What would be the best way to do this and do all images in this case have different ids or could they have the same id because they don't belong to the same User?
My Schema looks like this:
var userSchema = new Schema({
local: {
email: String,
password: String
},
facebook: {
id: String,
token: String,
email: String,
name: String
},
name: String,
about: String,
images: [{
id: Schema.ObjectId,
link: String,
main: Boolean
}]
});
When you are interested in the full object it is a simple find:
.find({"facebook.id":"<id>", "images.id":<image-id>})
I don't think that there is a way to reduce the image array in the result.
To update a single element in the image array you can use this:
.update({"facebook.id":"<id>", "images.id":<image-id>}, {$set : {"images.$.main" :false} } );
userSchema .find({facebook.id: "some ID",{ "images.id": { $in: [ id1, id2, ...idn] }}
since images are inside the document you can have same ID's however every time you query you should keep in mind that you send some other parameters such as facebook.id or facebook.email along with image id's to retrieve them. Otherwise you end up getting all that might be irrelevant only because you decide to keep same ID's for images.
tl;dr
I struggled with this and came up with a solution. Like you, I was trying to query for a deeply nested object by the _id, but I kept coming up empty with the results. It wasn't until I did some type checking that I realized the id value I was getting from my frontend, while directly supplied by mongoose, was in fact a String and not an Object.
I realize this question was already partially answered before, but that person's solution didn't work for me, and the comment on the answer tells me you wanted to update the specific image you queried for, which is exactly what I was trying to do.
The solution
In order to select an object from the nested array by the _id value, first you'll have to install the npm package bson-objectid and use the provided method to convert your string into an objectId in your query.
In your terminal:
npm i bson-objectid
In your code:
const ObjectId = require('bson-objectid')
userSchema.findOneAndUpdate(
{ "facebook.id": <user-id>, "images._id": ObjectId(<image-id>) },
{ "$set": { "images.$.main": false } },
{ new: true }, // an extra options parameter that returns the mutated document
(err, user) => {
if (err) {
handleErr(err)
} else {
console.log(user)
// do something with new user info
}
)

mongoose db - array insertion using create and save

How to insert array and normal variable data to mongoose database..
var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }], class: 10 })
parent.save(callback);
This is the method i know currently.
I need it to be done from the req.body. So how can I done after creating the parent object. ie
var parent = new Parent();
///code for inserting the array data and other normal datatypes
parent.save(callback);
Use the document instance like any other javascript object.
parent.children = [{ name: 'Matt' }, { name: 'Sarah' }];
parent.class = 10;
parent.save();
Just don't change it entirely (like doing parent = {...}), otherwise you'd have de-referenced the actual mongoose document instance. Only make changes on its properties like shown above.

backbone.js with backgrid.js to populate JSON

I am using backgrid.js with backbone.js. I'm trying to populate JSON (user list) in backgrid. Below is my JSON,
[{"name": "kumnar", "emailId":"kumar#xxx.com",
"locations":{"name":"ABC Inc.,", "province":"CA"}
}]
I can access name & emailId as below,
var User = Backbone.Model.extend({});
var User = Backbone.Collection.extend({
model: User,
url: 'https://localhost:8181/server/rest/user',
});
var users = new User();
var columns = [{
name: "loginId",
label: "Name",
cell: "string"
}, {
name: "emailId",
label: "E-mail Id",
cell: "string"
}
];
var grid = new Backgrid.Grid({
columns: columns,
collection: users
});
$("#grid-result").append(grid.render().$el);
userEntities.fetch();
My question is, how do I add a column for showing locations.name?
I have specified locations.name in the name property of columns but it doesn't work.
{
name: "locations.name",
label: "E-mail Id",
cell: "string"
}
Thanks
Both backbone and backgrid currently don't offer any support for nested model attributes, although there are a number of tickets underway. To properly display the locations info, you can either turn the locations object into a string on the server and use a string cell in backgrid, or you can attempt to supply your own cell implementation for the locations column.
Also, you may try out backbone-deep-model as it seems to support the path syntax you are looking for. I haven't tried it before, but if it works, you can just create 2 string columns called location.name and location.province respectively.
It's really easy to extend Cell (or any of the existing extensions like StringCell). Here's a start for you:
var DeepstringCell = Backgrid.DeepstringCell = StringCell.extend({
render: function () {
this.$el.empty();
var modelDepth = this.column.get("name").split(".");
var lastValue = this.model;
for (var i = 0;i<modelDepth.length;i++) {
lastValue = lastValue.get(modelDepth[i]);
}
this.$el.text(this.formatter.fromRaw(lastValue));
this.delegateEvents();
return this;
},
});
In this example you'd use "deepstring" instead of "string" for your "cell" attribute of your column. Extend it further to use a different formatter (like EmailFormatter) if you want to reuse the built-in formatters along with the deep model support. That's what I've done and it works great. Even better is to override the Cell definitions to look for a "." in the name value and treat it as a deep model.
Mind you, this only works because I use backbone-relational which returns Model instances from "get" calls.

Resources