How to iterate thru multiple values in a single key in mongoose - javascript

I have a web app which uses MongoDB as database and I'm trying to iterate thru multiple values inside a single property named passport.
This is my schema:
var EmployeeDBSchema = new Schema({
/* Passport tab schema */
passportInfo: {
passportDetails: []
},
And here's how it looks in Robomongo:
I tried checking if this can be retrieved as an array, so I did below:
console.log(_.map(results, _.property('passportInfo')));
passportArr = _.map(results, _.property('passportInfo'));
console.log("is passport array? " + _.isArray(passportArr));
Result:
Now since it was positive, I tried iterating thru it like a normal array using the ff. code:
_.forEach(passportArr, function (value, key) {
_.forEach(passportArr[key], function(value2, key2){
console.log(key2 + " >> " + value2);
});
});
However, what I got was this:
How can I get the values of passportExpiry, passportNumber and countryOfOrigin?
I'm really having a hard time over this. Hoping somebody can help.
Thank you.
EDIT: Not sure if this will help but, I got the idea for the structure from this Plunker. Main idea behind Passport was the user can add an unlimited number of passport information (hence the passportInfo array). I'm trying to retrieve the data here so I can render it as a CSV file.
UPDATE:
Here's the expanded results as requested (from console.log):
full results
[ { _id: dummyiddontmind123,
employeeID: '123asd12',
desiredRoleOther: 'Other role',
desiredRole3: 'Role 3',
desiredRole2: 'Role 2',
desiredRole1: 'The Role',
isOpenToIntlAssignment: 'Y',
employeeName: 'Jane Doe',
yrsInIT: 1,
visaInfo:
[ { visaCountryOfOrigin: [Object],
visaNumber: 'asd',
visaEntry: 'Single',
visaExpiry: '2017-03-16T16:00:00.000Z',
visaStatus: 'expired' } ],
passportInfo:
[ { countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-03' },
{ countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-08T16:00:00.000Z' },
{ countryOfOrigin: [Object],
passportNumber: [Object],
passportExpiry: '2017-03-10T16:00:00.000Z' } ] } ]
[ [ { passportExpiry: '2017-03-03',
passportNumber: { '0': 'EB1234567' },
countryOfOrigin: { '0': 'Philippines' } },
{ passportExpiry: '2017-03-08T16:00:00.000Z',
passportNumber: { '1': 'AS1234' },
countryOfOrigin: { '1': 'Japan' } },
{ passportExpiry: '2017-03-10T16:00:00.000Z',
passportNumber: { '2': 'AX123' },
countryOfOrigin: { '2': 'Singapore' } } ] ]

Your data inside passportInfo is a bit off, probably due to some copy-paste error after outputting it.
I take it you want to export all stored passport information into a csv of format country; number; expiry.
The first thing you want to make sure is that the actual data and the data you expect are structurally the same. If not, you can still add transformation steps before (e.g. flatten arrays or transform objects from {0: 123} to [123]).
As soon as this is under control, you can start by mapping the objects of employee.passportInfo from a structured object to an array of information necessary for your csv. This happens using Array.prototype.map.
I added another step inside that map to make sure an object of passportInfo.passportNumber of the form {0: 123} is transformed into an array [123]. This array is then used to map to a single line of your csv by adding passportInfo.countryOfOrigin and .passportExpiry.
// The following code snippets only operates on one employee. If you have an array use an iteration function depending on your needs.
const employee = { _id: 123,
employeeID: '123asd12',
desiredRoleOther: 'Other role',
desiredRole3: 'Role 3',
desiredRole2: 'Role 2',
desiredRole1: 'The Role',
isOpenToIntlAssignment: 'Y',
employeeName: 'Jane Doe',
yrsInIT: 1,
visaInfo: [ {
visaCountryOfOrigin: [Object],
visaNumber: 'asd',
visaEntry: 'Single',
visaExpiry: '2017-03-16T16:00:00.000Z',
visaStatus: 'expired' }
],
passportInfo: [ {
countryOfOrigin: 'ABC',
passportNumber: { 0: '123123123' },
passportExpiry: '2017-03-03'
}, {
countryOfOrigin: 'DEF',
passportNumber: { 0: '321321321', 1: '123123123' },
passportExpiry: '2017-03-08T16:00:00.000Z'
}, {
countryOfOrigin: 'GHI',
passportNumber: { 0: '654654654' },
passportExpiry: '2017-03-10T16:00:00.000Z'
} ]
};
const flattenPassportNumbers = numbers =>
Object.keys(numbers).map(key => numbers[key]);
const info = employee.passportInfo.map(({passportNumber, passportExpiry, countryOfOrigin}) =>
flattenPassportNumbers(passportNumber).map(number =>
[countryOfOrigin, number, passportExpiry]
)
);
const flattenLine = ([line]) => line;
const joinLine = (line) => line.join('; ');
const lines = info.map(flattenLine);
console.log(lines.map(joinLine));
console.log(lines.map(joinLine).join('\n'));
If there's something you don't understand, please don't hesitate to ask.

Related

Reduce an array of objects based on an object array property

I need help from some JavaScript/NodeJS experts. I'm using the v14 of NodeJS.
I would like to create a function that takes as an input this kind of array (let's say that it's a list of teams):
[
{
name: 'IT',
tags: ['Department', 'Section', 'Organizational']
},
{
name: 'Male',
tags: ['Gender', 'Organizational']
},
{
name: 'Foo',
tags: []
}
]
... and returns as an output a list of teams by tag name like this:
// Output:
{
Department: 'IT',
Section: 'IT',
Organizational: 'IT, Male',
Gender: 'Male'
}
The order of object keys as well as the order of the team names don't matter. I can do this quite easily with a few lines of code, but I'm quite sure that it would be easy to do using a few of our magic map(), reduce() functions and other utilities like spreading.
Anybody can help me achieve this in an optimized way?
Thank you!
Try this:
const organization = [
{
name: 'IT',
tags: ['Department', 'Section', 'Organizational']
},
{
name: 'Male',
tags: ['Gender', 'Organizational']
},
{
name: 'Foo',
tags: []
}
]
const result = organization.reduce((acum, current) => {
current.tags.forEach(tag => {
if(acum[tag]) acum[tag] = `${acum[tag]}, ${current.name}`
else acum[tag] = current.name
})
return acum
},{})
console.log(result)

json-rules-engine processing array of objects

Any help would be appreciated !! I couldn't find an answer.
Given input facts to the engine such as -
const facts = {
cart: {
prop1: true,
prop2: "My Cart",
prop3: {
prop4: "North America"
},
products: [
{
category: 1,
classification: null
},
{
category: 2,
classification: null
},
{
category: 1,
classification: null
}
]
}
};
I want to be able to process each object in the products array and define a separate rule for each category and set the classification field for that category.
Something like -
let condition1 = {
all: [
{
fact: 'category',
operator: 'equal',
value: 1
}
]
};
let condition2 = {
all: [
{
fact: 'category',
operator: 'equal',
value: 2
}
]
};
let event1 = {
type: 'category 1 event'
// Update classification
};
let event2 = {
type: 'category 2 event'
// Update classification
};
How do I do this? Do i set the classification field in the event handler for that event? How do I access the object the category belongs to?
I tried using the below, but it selects all the category values from each object. I want to be able to process each object separately.
let condition = {
all: [
{
fact: 'cart',
operator: 'contains',
value: 1,
path: '$.products[*].category'
}
]
}
I cant add them as runTime facts either since you can have only 1 runtime fact and its value. (No Duplicates)

Node.js - Access key from object

I try to access a key from an object I get back from an API but when I do so, I get the key of the object in a strange format.
This is what I get when I console.log the object (booking):
{ createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers:
List [
{ value: 100,
code: 'vouchercode',
...
}
]
}
When I then try to console.log the "vouchers" key:
booking.vouchers
I get this:
{ [Function: f]
_receiver: {
createdDate: 2018-03-26T11:36:09.694Z,
date: 2018-03-26T13:45:00.000Z,
...,
vouchers: List [ [Object] ] },
_scope:
{ where: { bookingId: 5ab8db29b24991b50704445a },
collect: 'voucher',
include: 'voucher' },
_targetClass: 'Voucher',
find: [Function],
getAsync: [Function],
...,
}
Why do I get it in this format and how do I convert it to a normal object like this?:
vouchers: [
{ value: 100,
code: 'vouchercode',
...
}
]
I hope the problem is understandable and some of you can help :)
Edit:
This is my code:
Booking.findById id, {include:[ 'vouchers']}, (err, booking)->
console.log booking
vouchers = booking.vouchers
console.log vouchers
*Note: I know this is coffeescript but I don't think thats the problem

Filtering a list of objects by a child array in Angular 2

I have data that looks like this
[
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
]
I want to be able to type into a search bar and filter the data to search for related tags. There was a built in filter pipe for this in angular 1 but it looks like it has been removed in angular 2. I've been looking into custom pipes but the only way I can think to do it is with a nested loop that loops over all of the objects then loops through the tags. Am I thinking about this wrong. Is there an easier way to do this or a built in function that would work for this?
You can just use normal javascript APIs to get that behaviour:
data = [
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
];
filterDataByTag(searchTerm: string) {
// filter the data array, based on some condition
return this.data.filter(item => {
// only include an item in the filtered results
// if that item's Tags property includes the searchTerm
// includes is a built in array method in ES2016
return item.Tags.includes(searchTerm);
});
}
In my example, i'm harding coding the data, but you can adjust to suit your situation. The key point is the function returns a filtered list of the data based on the searchTerm, so you can just call this method each time you want to refresh your filtered list (for eg on the input event of your search field)
You should reorganize data into a reverse index store :
export interface StoreData {
Tag: string;
Peoples: People[] = [];
}
const store: StoreData[] = [];
export interface People {
id: number;
Name: string;
Tags: string[];
}
loadPeopleStore(peoples: People) {
peoples.forEach(p => {
p.Tags.forEach(t => {
let storeData = store.filter(d => d.Tag === t);
if(storeData.length == 1) {
storeData[0].Peoples.push(p);
} else {
store.push({Tag: t, Peoples[p]});
}
}
}
}
initYourPipe() {
let peoples: People[] = [
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
]
this.loadPeopleStore(peoples);
}

How can I remove object from array, with Lodash?

I'm trying to remove an object from an array using Lodash.
In server.js (using NodeJS):
var lodash = require('lodash')();
var rooms = [
{ channel: 'room-a', name: 'test' },
{ channel: 'room-b', name: 'test' }
]
I tried with two commands and it did not work:
var result = lodash.find(rooms, {channel: 'room-a', name:'test'});
var result = lodash.pull(rooms, lodash.find(rooms, {channel: 'room-a', name:'test'}));
Here's the output of console.log(result):
LodashWrapper {
__wrapped__: undefined,
__actions__: [ { func: [Function], args: [Object], thisArg: [Object] } ],
__chain__: false,
__index__: 0,
__values__: undefined }
Can someone help me? Thank you!
_.remove() is a good option.
var rooms = [
{ channel: 'room-a', name: 'test' },
{ channel: 'room-b', name: 'test' }
];
_.remove(rooms, {channel: 'room-b'});
console.log(rooms); //[{"channel": "room-a", "name": "test"}]
<script src="https://cdn.jsdelivr.net/lodash/4.14.2/lodash.min.js"></script>
I'd go for reject() in this scenario. Less code:
var result = _.reject(rooms, { channel: 'room-a', name: 'test' });
require('lodash')()
Calling the lodash function (by ()) creates a LoDash object that wraps undefined.
That's not what you want; you want the lodash function itself, which contains static methods.
Remove that.

Categories

Resources