How to map properties of an object to another? - javascript

I know there are many questions on this matter, but I can't figure out how to apply it in my case.
Code is as following:
const mailDocumentSchema = new schema.Entity('mailDocuments', {}, { idAttribute: 'identifier' });
const mailSchema = new schema.Entity('mails', { emailDocument: [mailDocumentSchema] }, { idAttribute: 'identifier' });
const mailAccountSchema = new schema.Entity('mailAccounts', { mails: [mailSchema] }, { idAttribute: 'address' });
const mailMapper = (item: any): Mail => ({
id: item.identifier,
title: item.subject,
documents: item.emailDocument,
subject: item.realSubject,
receiver: item.receiver,
createdDate: item.createdDate,
sendDate: item.sendDate,
body: item.body
});
const mailDocumentMapper = (item: any): MailDocument => ({
id: item.identifier,
docId: item.oldDocId,
name: item.name,
createdDate: item.createdDate,
bodyStatus: item.bodyStatus
});
export const undefinedDocumentsMapper = (response: any[]): NormalizedMailbox => {
const undefinedDocuments = map(groupBy(response, item => item.receiver), (item, key) => ({ name: null, address: key, mails: item }));
const normalizedResponse = normalize(undefinedDocuments, [mailAccountSchema]);
return {
mailAccounts: Object.values<MailAccount>(normalizedResponse.entities.mailAccounts),
mails: Object.values<any>(normalizedResponse.entities.mails).map(mailMapper),
mailDocuments: Object.values<any>(normalizedResponse.entities.mailDocuments).map(mailDocumentMapper)
};
};
API response is:
[
{ identifier: "...", title: "...", receiver: "...", emailDocuments: [{...}] },
...
]
What I want is to map the receiver and title properties from mails entity objects to mailDocuments entity objects.
As a result to get mailDocuments entity objects as such:
{
id: "...",
docId: "...",
name: "...",
createdDate: "...",
bodyStatus: ...,
title: "...",
receiver: "..."
}
How to accomplish this?

If I understand correctly, you can do the following:
mails.forEach(mail => {
mail.documents.forEach(document => {
document.receiver = email.receiver
document.title = email.title
})
})

Related

GraphQL Expected Iterable but did not find field

I am trying to implement GraphQL but always get the error of Expected iterable. As I understand there can be an error with the types, but i tried everything and don't know what to do
that's what my API returns
{
"data": [
{
"id": "bitcoin",
"rank": "1",
"symbol": "BTC",
"name": "Bitcoin",
"supply": "17193925.0000000000000000",
"maxSupply": "21000000.0000000000000000",
"marketCapUsd": "119150835874.4699281625807300",
"volumeUsd24Hr": "2927959461.1750323310959460",
"priceUsd": "6929.8217756835584756",
"changePercent24Hr": "-0.8101417214350335",
"vwap24Hr": "7175.0663247679233209"
},
......
]
}
and here is my code
const coinType = new GraphQLObjectType({
name: 'Coin',
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
})
});
// Root Query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
coin: {
type: new GraphQLList(launchType),
resolve(parent, args) {
return axios
.get('https://api.coincap.io/v2/assets')
.then(res => res.data);
}
},
})
});
module.exports = new GraphQLSchema({
query: RootQuery
});
Usually this is because mismatch between the return type of the resolver and your schema. Check for returning Object instead of Array or something in that sense. You may post the schema just in case.

Map function is not setting value to each element

I'm using map function to set values to the array of objects. but whenever i pass multiple objects it only stores only last one. I can't find why it is doing this.
const [tracks, setTracks] = useState([]);
const [playerTracks, setPlayerTracks] = useState([])
const playTracks = () => {
setPlayerTracks(
{ id: 8, track_name: "Bad Guy", url: "001.mp3", artwork: "001.jpg", artist: "Ed Sheeran" },
{ id: 9, track_name: "Bury A Friend", url: "002.mp3" , artwork: "002.jpg", artist: "Taylor Swift"}
)
playerTracks.map(track => {
setTracks([{
title: track.track_name,
artist: track.artist_name,
audioSrc: track.url,
image: track.artwork
}])
})
console.log(playerTracks) // both objects
console.log(tracks) // only last object
}
Instead of updating state in map, you need to create new object and then store into state like below:-
const [tracks, setTracks] = useState([]);
const [playerTracks, setPlayerTracks] = useState([])
const playTracks = () => {
setPlayerTracks(
{ id: 8, track_name: "Bad Guy", url: "001.mp3", artwork: "001.jpg", artist: "Ed Sheeran" },
{ id: 9, track_name: "Bury A Friend", url: "002.mp3" , artwork: "002.jpg", artist: "Taylor Swift"}
)
const newTracks = playerTracks.map(track => {
return {
title: track.track_name,
artist: track.artist_name,
audioSrc: track.url,
image: track.artwork
};
})
setTracks(newTracks);
}

JavaScript: Insert property into an object during loop

I'm looping an array of objects taken from MongoDB and attempting to insert a property into one of them, without success.
The array of objects would be:
[
{
_id: [String],
customerInformation: [ [Object] ],
purchasedBanners: [ [Object] ],
statusOfPurchase: 'new',
createdAt: 2021-02-24T15:04:42.074Z,
updatedAt: 2021-02-24T15:04:42.074Z,
__v: 0
}
...
]
I've tried:
return PurchasesModel.schemaForPurchases.find({
statusOfPurchase: args.statusOfPurchase
})
.limit(10)
.then(purchases => {
purchases.forEach(purchase => {
NotesModel.schemaForNotes.countDocuments({ purchaseId: purchase._id })
.then(numberOfNotes => {
Object.defineProperty(purchase, 'numberOfNotes', {
value: numberOfNotes
})
})
})
return purchases
})
But then I found that the forEach method is synchronous, so I tried:
return PurchasesModel.schemaForPurchases.find({
statusOfPurchase: args.statusOfPurchase
})
.limit(10)
.then(purchases => {
for (let i = 0; i < purchases.length; i++) {
let numberOfNotes = 0
numberOfNotes = NotesModel.schemaForNotes.countDocuments({ purchaseId: purchases[i]._id })
.then(numberOfNotes => {
return numberOfNotes
})
Object.defineProperty(purchases[i], 'numberOfNotes', {
value: numberOfNotes.then(numberOfNotes => {
return numberOfNotes
})
})
}
return purchases
})
In each case (including several other approaches), the objects aren't appended.
I'm new to MongoDB, so I assume I'm either doing something wrong, or perhaps the objects are somehow protected?
Thoughts welcome.
In the end, there wasn't a shortcut! Or at least I'm not aware of it.
const GET_ALL_PURCHASES_QUERY = (statusOfPurchase) => {
return gql`
query {
getAllPurchases(statusOfPurchase: "${statusOfPurchase}") {
id
customerInformation {
customerName
customerEmailAddress
}
purchasedBanners {
nameOfBanner
costOfBanner
numberOfBannersToPrint
nameOfChosenComponent
targetPDF
previewImage
dataToExport
}
numberOfNotes {
count
}
createdAt
updatedAt
}
}
... and then:
const NotesCountForPurchaseType = new GraphQLObjectType({
name: 'NotesCountForPurchase',
fields: () => ({
count: {
type: GraphQLInt
}
})
})
const PurchaseType = new GraphQLObjectType({
name: 'Purchase',
fields: () => ({
id: {
type: GraphQLID
},
customerInformation: {
type: GraphQLList(PurchaseCustomerInformationType)
},
purchasedBanners: {
type: GraphQLList(PurchaseBannerType)
},
statusOfPurchase: {
type: GraphQLString
},
createdAt: {
type: GraphQLDateTime
},
updatedAt: {
type: GraphQLDateTime
},
numberOfNotes: {
type: NotesCountForPurchaseType,
resolve(parent, args) {
return NotesModel.schemaForNotes.countDocuments({
purchaseId: parent.id
})
.then(numberOfNotes => {
console.log('Schema:numberOfNotes()', numberOfNotes)
return { count: numberOfNotes }
})
}
}
})
})
Extra work, but working.

Javascript - transforming an object of array list to new formated one?

I'm trying to transform an object contain array to another one with javascript. Below is an example of the object field and what the formatted one should look like.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
I need The new Fields to looks like this
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]},
One contributor suggested me a method like this but i think something need to modify in it but couldn't figure it out.
export const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title: {en})=>({name: en, value: code}))
}))
});
// newFields= transform(Fields)
I'm new working with javascript so any help is greatly appreciated, Thanks.
const transform = (o) => {
return Object.entries(o).map((e)=>({
name: e[0],
tags: e[1].map((k)=>({name: (k.title)?k.title.en:undefined, value: k.code}))
}))[0]
}
console.log(transform({
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
}))
Using the entries method you posted:
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
// 1. Obtain keys and values from first object
Fields = Object.entries(oldFields);
// 2. Create new object
const newFields = {};
// 3. Create the name key value pair from new Fields array
newFields.name = Fields[0][0];
// 4. Create the tags key value pair by mapping the subarray in the new Fields array
newFields.tags = Fields[0][1].map(entry => ({ name: entry.title.en, value: entry.code }));
Object.entries(Fields) will return this:
[
"GAME",
[TagsArray]
]
And Object.entries(Fields).map will be mapping this values.
The first map, will receive only GAME, and not an array.
Change the code to something like this:
export const transform = (Fields) => {
const [name, tags] = Object.entries(Fields);
return {
name,
tags: tags.map(({ code, title }) => ({
name: title.en,
value: code
}))
}
}
Hope it help :)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
let newFields = {
name: 'GAME',
tags:[
{ name: 'playPES', value: "{{PES}}" },
{ name: 'playFIFA', value: "{{FIFA}}" }
]
}
let answer = {
name: "Game",
tags: [
]
}
Fields.GAME.map(i => {
var JSON = {
"name": i.title.en,
"value": i.code
}
answer.tags.push(JSON);
});
console.log(answer);
I think that this is more readable, but not easier... If you want the result as object you need to use reduce, because when you do this
Object.keys(Fields)
Your object transform to array, but reduce can change array to object back.
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const result = Object.keys(Fields).reduce((acc, rec) => {
return {
name: rec,
tags: Fields[rec].map(el => {
return {
name: el.title.en,
value: el.code
}
})
}
}, {})
console.log(result)
let Fields = {
GAME: [
{ code: '{{PES}}', title: { en: "playPES"} },
{ code: '{{FIFA}}', title: { en: "playFIFA " } },
]
};
const transform = (fields) => ({
tags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
tags: innerFields.map(({code, title: title,en})=>({name: title.en, value: code}))
}))
});
//check required output in console
console.log(transform(Fields));

mongodb after updating document, returns old values

router.delete('/deletepost', (req, res) => {
// console.log(req.query.postid)
if (req.query.category === 'forsale') {
ForSalePosts.findById(req.query.postid)
// .then(post => console.log(post))
.deleteOne()
.catch(err => console.log(err))
AllPosts.updateOne({ user: req.query.userid },
{ $pull: { posts: { postid: req.query.postid } } })
.catch(err => console.log(err))
AllPosts.aggregate(
[
{ $match: { user: ObjectId(req.query.userid) } },
{ $unwind: '$posts' },
{ $sort: { 'posts.date': -1 } }
]
)
.then(posts => {
// console.log(posts)
res.json(posts)
})
.catch(err => res.status(404).json({ nopostfound: 'There is no posts' }))
}
})
this is my route. i am trying to delete an item in my document. the item is being deleted however it returns old values. for example :
Allposts has an array with posts:[postid:{type:String}, ...]
I am trying to delete a specific postid by using $pull,
postid is being deleted however when I aggregate the same model, .then(posts=> console.log(posts)) returns old values on first call, doesnt update the component.
EDIT: just realized sometimes it returns the right values but sometimes it returns the old values as well. does anyone know why and what can i do to solve it ?
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const AllPostsSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
posts: [{
postid: {
type: String
},
title: {
type: String
},
category: {
type: String
},
subcategory: {
type: String
}, category: {
type: String
},
description: {
type: String
},
name: {
type: String
},
price: {
type: Number
},
email: {
type: String
},
phonenumber: {
type: Number
},
language: {
type: String
},
make: {
type: String
},
model: {
type: Number
},
odometer: {
type: Number
},
condition: {
type: String
},
state: {
type: String
},
town: {
type: String
},
city: {
type: String
},
links: [{ type: String }],
date: {
type: Date,
default: Date.now
}
}]
})
module.exports = AllPosts = mongoose.model('allposts', AllPostsSchema)
REACT FUNCTION CALL :
deletePost = (category, postid) => {
const postinfo = {
category: category.toLowerCase(),
postid: postid,
userid: this.props.auth.user.id
}
this.props.deletePost(postinfo)
}
You need to add options parameter to delete like:
AllPosts.updateOne({ user: req.query.userid },
{
$pull: { posts: { postid: req.query.postid } }
},
{ new: true }
);
This will return the new object after performing the operation. Hope this works for you.
All the mongo queries return partial promise. You have to use .then in order to resolve each promises.
Here you are running all the queries in series without using .then or async-await. So whenever you $pull from AllPosts after that immediately you call the AllPosts aggregate query which sometimes get executed and sometimes it doesn't.
So in order to make it run one by one you have to use either .then or async-await.
router.delete("/deletepost", (req, res) => {
if (req.query.category === "forsale") {
ForSalePosts.findById(req.query.postid)
.deleteOne()
.then(() => {
AllPosts.updateOne(
{ "user": req.query.userid },
{ "$pull": { "posts": { "postid": req.query.postid } } }
)
.then(() => {
AllPosts.aggregate([
{ "$match": { "user": ObjectId(req.query.userid) } },
{ "$unwind": "$posts" },
{ "$sort": { "posts.date": -1 } }
]).then(posts => {
// console.log(posts)
res.json(posts);
});
})
.catch(err =>
res.status(404).json({ "nopostfound": "There is no posts" })
);
});
}
})

Categories

Resources