Sequelize magic method returning null - javascript

Just a bit confused as to why this magic method is returning null. It's probably very simple, but I'm using methods I wouldn't normally (bulkingCreating) and can't currently see it.
Association: Country.hasOne(Capital, { foreignKey: 'countryId' });
Populating dummy data:
const countries = await Country.bulkCreate([
{ name: 'England' },
{ name: 'Spain' },
{ name: 'France' },
{ name: 'Canada' }
]);
const capitals = await Capital.bulkCreate([
{ name: 'London' },
{ name: 'Madrid'},
{ name: 'Paris' },
{ name: 'Ottawa' }
]);
countries.forEach((country, index) => {
country.setCapital(capitals[index]);
});
const country = await Country.findOne({where: {name: 'Spain'}});
console.log(country.name, Object.keys(country.__proto__)); // Spain / magic methods
const capital = await country.getCapital();
console.log(capital); // null
The table:
Am I wrong in thinking country.getCapital() should return the relevant entry?

As you might guess setCapital should be an async function because it makes changes in DB so you need to use for instead of forEach method that does not support async callbacks:
let index = 0;
for (const country of countries) {
await country.setCapital(capitals[index]);
index += 1;
}
It would be better to create countries one by one and create capitals for them not relying on the same indexes of both collections (DB might return created records in a different order).

If you are using Sequelize 5.14+, you can do this in 1 bulkCreate using include option.
const countries = await Country.bulkCreate([
{
name: 'England',
Capital: { // This keyname should be matching with model name.
name: 'London'
}
},
{
name: 'Spain',
Capital: {
name: 'Madrid'
}
},
...
],
{
include: Capital,
returning: true // If Postgres, add this if you want the created object to be returned.
}
);

Related

Trying to return a filter() value from an array of objects based on conditionals

I'm trying to return only a part of my object as an array based on conditionals but I'm kinda stumped.
I have an array of objects and I want to return an array of names for each key : value they fit in.
I do get only the unique pairings but I'm returning the food key:value as well and all of it is still inside an object not a new array. Some insight would be greatly appreciated. Newer to coding.
const organizeNames = function (foods) {
let foodNames = foods.filter((names) => {
if (names.food === 'oranges') {
return names.name;
}
});
console.log(foodNames);
};
console.log(
organizeNames([
{ name: 'Samuel', food: 'oranges' },
{ name: 'Victoria', food: 'pizza' },
{ name: 'Karim', food: 'pizza' },
{ name: 'Donald', food: 'pizza' },
])
);
You're really close here. What you need to incorporate is .map() to map your list of objects to a list of names. Your filter part works, partly by accident, so I've fixed it to be more correct (return names.food === 'oranges'), and then once you have your list of objects that match 'oranges' for their food, you map that filtered list into a list of names by doing .map(names => names.name)
const organizeNames = function (foods) {
let foodNames = foods.filter((names) => {
// only keep items whose .food property === 'oranges'
return names.food === 'oranges'; // returns true or false
}).map(names => {
// map the filtered list of objects into a list of names by
// returning just the object's .name property
return names.name;
});
return foodNames;
};
console.log(
organizeNames([
{ name: 'Samuel', food: 'oranges' },
{ name: 'Victoria', food: 'pizza' },
{ name: 'Karim', food: 'pizza' },
{ name: 'Donald', food: 'pizza' },
])
);
The filter() callback function should just return true or false. Then you can use map() to get a specific property from each of the filtered items.
const organizeNames = function(foods) {
let foodNames = foods.filter((names) => names.food == 'oranges').map(names => names.name);
return foodNames;
}
console.log(
organizeNames([{
name: 'Samuel',
food: 'oranges'
},
{
name: 'Victoria',
food: 'pizza'
},
{
name: 'Karim',
food: 'pizza'
},
{
name: 'Donald',
food: 'pizza'
},
])
);

Returning an array of all the pet names

If I were to create a function, were a persons name was entered, how would I return an array with the names of the pets from the object below, what would be the best method if I were to use a for loop to iterate over it? I've not quite learnt some of the ES6 features yet and i'm new to coding.
A typical array of owners is shown below:
[
{
name: 'Malcolm',
pets: ['Bear', 'Minu'],
},
{
name: 'Caroline',
pets: ['Basil', 'Hamish'],
},
];
Thanks for the fast replies! :)
It's pretty simple to achieve it:
you search for the corresponding owner with the find function, then, if you have an owner, you return the pets key, which is already an array according to the code provided. If you have no owner corresponding to the name entered, then you'll get "undefined", but you can customise this code to have an empty array if it better fits your needs.
const data = [{
name: 'Malcolm',
pets: ['Bear', 'Minu'],
}, {
name: 'Caroline',
pets: ['Basil', 'Hamish'],
}, ];
const getPetsByOwnerName = (ownerName) => {
const owner = data.find(d => d.name === ownerName);
return owner ? owner.pets : undefined;
}
const carolinePets = getPetsByOwnerName('Caroline');
console.log(carolinePets);
EDIT: author request to do it with a loop
const data = [{
name: 'Malcolm',
pets: ['Bear', 'Minu'],
}, {
name: 'Caroline',
pets: ['Basil', 'Hamish'],
}, ];
function getPetsByOwnerNameWithLoop(ownerName) {
for (let i = 0; i < data.length; i++) {
if (data[i].name === ownerName) {
return data[i].pets;
}
}
return undefined;
}
const carolinePets = getPetsByOwnerNameWithLoop('Caroline');
console.log(carolinePets);
let ownersArray = [ { name: 'Malcolm', pets: ['Bear', 'Minu'], }, { name: 'Caroline', pets: ['Basil', 'Hamish'], }, ];
const petArray = (owner, ownersArray) => {
let array = ownersArray.filter((arr) => arr.name===owner)
return array.length>0 ? array[0].pets : 'owner not found'
}
console.log(petArray("Caroline", ownersArray))
Try filter() method. The function returns an array of names from the filtered owner as a result.
Example code:
const arr = [
{ name: 'Malcolm', pets: ['Bear', 'Minu'], },
{ name: 'Caroline', pets: ['Basil', 'Hamish'], }
];
function petsNames(val) {
return arr.filter(x => x.name === val)[0].pets;
};
console.log(petsNames('Malcolm'));

Map the nested data from other table using promise and async-await

I need the expert advice for this code. I need to know Is there any better way to solve this.
I am using the mongoose for db. I have a dataset like this:
Below is matchTable:
{
_id: 617bc0113176d717f4ddd6ce,
car: [],
status: true
},
{
_id: 617bc0113176d717f4ddd6cg,
car: [
{
aid: '5c1b4ffd18e2d84b7d6febcg',
}
],
status: true
}
And I have a Car table in which car name is there on behalf of id
like this
{ _id: ObjectId('5c1b4ffd18e2d84b7d6febce'), name: 'ford' },
{ _id: ObjectId('5c1b4ffd18e2d84b7d6febcg'), name: 'mitsubishi' },
So I want to make join the data from car table, so that response get name on behalf of aid.
Desired result will be like
{
_id: 617bc0113176d717f4ddd6ce,
car: [],
status: true
},
{
_id: 617bc0113176d717f4ddd6cg,
car: [
{
aid: '5c1b4ffd18e2d84b7d6febcg',
name: 'mitsubishi'
}
],
status: true
}
For that I have to merge the car table on matchTable. I have done this but I want to give some suggestion that is there any better way to do or is it fine. I need expert advice.
const getData = await matchTable.find(
{ status: true }
).lean().exec();
let dataHolder = [];
await Promise.all (
getData.map(async x => {
await Promise.all(
x.car.map(async y => {
let data = await Car.findOne(
{ _id: ObjectId(y.aid) },
{ name: 1 }
).lean().exec();
y.name = '';
if (data) {
y.name = data.name;
}
})
)
// If I return { ...x }, then on response it will return {}, {} on car column
dataHolder.push(x) //So I have chosen this approach
})
);
Please guide me if any better and efficient solution is there. Thanks in advance
You can make use of aggregation here.
const pipeline = [
{
$match : { status : true }
},
{
$unwind: '$matchtable',
},
{
$lookup: {
from: "cars",
localField: "car.aid",
foreignField: "_id",
as: "matchcars"
}
},
{
$addFields: {
"car.carName": { $arrayElemAt: ["$matchcars.name", 0] }
}
},
{
$group: {
_id: "$_id",
cars: { $push: "$matchcars" }
}
}
]
const result = await matchTable.aggregate(pipeline).exec();
Please make sure, aid field inside car array (in matchTable collection) is an ObjectId because its being matched to _id (which is an ObjectId) inside cars collection.

how do i create a new object based off an array and another object?

I am trying to create a new object based off an existing array. I want to create a new object that show below
{ jack: 'jack', content: 'ocean'},
{ marie: 'marie', content: 'pond'},
{ james: 'james', content: 'fish biscuit'},
{paul: 'paul', content: 'cake'}
const words = ['jack','marie','james','paul']
const myUsers = [
{ name: 'jack', likes: 'ocean' },
{ name: 'marie', likes: 'pond' },
{ name: 'james', likes: 'fish biscuits' },
{ name: 'paul', likes: 'cake' }
]
const usersByLikes = words.map(word => {
const container = {};
container[word] = myUsers.map(user => user.name);
container.content = myUsers[0].likes;
return container;
})
I am not getting the correct object, but instead it returns a list.
[ { jack: [ 'shark', 'turtle', 'otter' ], content: 'ocean'}, { marie: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ james: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ paul: [ 'shark', 'turtle', 'otter' ], content: 'ocean'} ]
What is the role of words array? I think the below code will work.
const result = myUsers.map(user => ({
[user.name]: user.name,
content: user.likes
}));
console.log('result', result);
In case, if want to filter the users in word array then below solution will work for you.
const result = myUsers.filter(user => {
if (words.includes(user.name)) {
return ({
[user.name]: user.name,
content: user.likes
})
}
return false;
});
You can achieve your need with a single loop.
The answer #aravindan-venkatesan gave should give you the result you are looking for. However important to consider:
When using .map() javascript returns an array of the same length, with whatever transformations you told it to inside map().
If you want to create a brand new object, of your own construction. Try using .reduce(). This allows you to set an input variable, i.e: object, array or string.
Then loop over, and return exactly what you want, not a mapped version of the old array.
See here for more details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

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);
}

Categories

Resources