How to push an item to the array inside JSON Object? - javascript

I am trying to make inventory functionality using Discord.js and struggling on how to push an item to the array inside JSON Object.
Inside the JSON, every user with unique 'userID' has their own array 'inventory'.
The thing I want to achieve is:
After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated.
.json file:
{
"userID": {
"inventory": []
}
}
.js file:
const item = itemName
inventory[userID] = {
inventory: inventory[userID].inventory + item,
}
fs.writeFile('./data/inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})
Output (after using command twice):
{
"userID": {
"inventory": ["itemNameitemName"]
}
}
Expected output (after using command twice):
{
"userID": {
"inventory": ["itemName", "itemName"]
}
}
The thing I want to achieve is: After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated. I suppose I need to use .push() somewhere, but I tried it million times in all configurations I could think of and it always throws an error, that .push() is not a function.

Instead of making a new object for the user every time you want to update the inventory, it would be much easier if you can just push the item to the inventory instead of reassigning. #DanielAWhite wrote the correct solution but I think you misunderstood where to put that particular piece of code. What you might have tried is this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID] = {
inventory: inventory[userID].inventory.push(item),
}
console.log(inventory)
Instead, what the correct way was to do away with the inventory[userID] = {} part and just directly push the item to the inventory by doing this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID].inventory.push(item)
console.log(inventory)
(Note: I edited the code a little bit so that you could try to run this code right here, but this should work with your fs.writeFile as well

Try this :
let rawdata = fs.readFileSync('inventory.json');
let inventory = JSON.parse(rawdata);
inventory["userID"] = {
inventory: [...inventory["userID"].inventory, item],
}
fs.writeFile('./inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})

Related

insert many don’t working in mongo DB why?

I am trying to insert many in mongoDB using mongoose’s .it only save one collection only why
Here is my code
https://codesandbox.io/s/gallant-solomon-o91wp
I save like that
app.get("/saveData", async () => {
try {
const data = [
{
empid: "test123",
date: "19-Jul-2019"
},
{
empid: "test13",
date: "18-Jul-2019"
},
{
empid: "test13",
date: "11-Jul-2019"
}
];
console.log("before save");
let saveBlog = await BlogPostModel.collection.insertMany(data, {
checkKeys: false
}); //when fail its goes to catch
console.log(saveBlog); //when success it print.
console.log("saveBlog save");
} catch (error) {
console.log(error);
}
});
try to fetch data like that
app.get("/filter", async (req, res) => {
try {
let filterBlog = await BlogPostModel.find({});
//when fail its goes to catch
console.log(filterBlog); //when success it print.
res.send(filterBlog);
} catch (error) {
console.log(error);
}
});
showing only one document
So, here as i suspected, there is one more index present in the collection you created i.e blogposts. the index is id [key id name id_1].
Here is your whole project, i have added in glitch.
Demo
and here i also have added one api /indexes , this retrieves all indexes of the collection. by default _id should be there, additional indexes are added after. so here you can see id, which needs to be unique.
i have made few more changes to your code.
The route /saveData now able to insert records. and it has the field called id which is unique.
but, the old route that is now at /saveData_old, which will give you error as there are no keys that represents this index key [id]. [also after inserting one, it will have id null and rest will fail, just causing duplicate ]
now you can either use id key with unique values, or if you don't need you can also drop the index as well. you can find an answer here for how to drop index.

How to fix "TypeError: Cannot read property 'node' of undefined" when creating pages programmatically in gatsbyjs

I am trying to create a blog using gatsbyjs, and would like for my blog pages to be created programmatically instead of explicitly creating them in the /src/pages folder.
I am currently trying to query the data from contentful, which I managed to do successfully according to GraphiQL. I followed the steps presented in the documentation for the most part, but I keep on encountering this error whenever my program steps into the ".forEach" function.
exports.createPages=({graphql,actions})=>{
const {createPage}=actions
const blogPost= path.resolve('./src/components/blogComponents/blog-post.js')
return new Promise((resolve,reject)=>{
graphql(`
{
allContentfulBlog{
edges{
node{
slug
}
}
}
}
`).then(results=>{
// console.log(results)
if(results.error){
reject(results.error)
}
// create blog post pages
const posts=results.data.allContentfulBlog.edges
console.log(post)
posts.forEach((post,index)=>{
console.log(`showing slugs: ${posts.node.slug}`)
const previous= index === posts.length-1?null: post[index+1].node
const next= index === 0?null: posts[index-1].node
createPage({
path:post.node.slug,
component:blogPost ,
context:{
slug:post.node.slug,
previous,
next
}
})
})
}).then(resolve)
})
This is the schema of the returned result
"data": {
"allContentfulBlog": {
"edges": [
{
"node": {
"slug": "web-developer-roadmap"
}
},
{
"node": {
"slug": "web-fundamentals-1"
}
}
]
}
}
I expected the "forEach" function to loop through all my blogs and assign the appropriate values the "createPage" function, but instead, it keeps on showing telling me that property of node available in my query is not defined even though I confirmed its presence by logging it to the console as can be seen in the "forEach" function.
The problem with your code it that you are trying to access object like an array
const previous= index === post.length-1?null: post[index+1].node
const next= index === 0?null: post[index-1].node
In the above code, post is single object. i:e { node: {} } and you are accessing it like an array post[index+1].node.
const posts =[
{
node: {
slug: "lorem"
}
},
{
node: {
slug: "ipsum"
}
}
];
posts.forEach((post, i) => {
// post is a single object. To access it's node, you need to use post.node
console.log("current post", post);
// To access the next post based on index
if(i<posts.length-1) {
console.log("Next node", posts[i + 1].node);
}
});
If you want to iterate on the next post based on index, use posts[index-1].node. As well make sure to check index, because for last element, index+1 will throw error.

React, Firebase: Access values of JSON and also get key value

I am beginner working with firebase, react. I am able to get the required data from firebase based on userEmail. But I am very confused in accessing the data.
firebase.database().ref('/users').orderByChild('email').equalTo(userEmail).on('value', data => {
console.log('data: ', data);
})
I get the following output:
data: Object {
"-Lhdfgkjd6fn3AA-": Object {
"email": "t5#gmail.com",
"favQuote": "this is it",
"firstName": "t5",
"lastName": "l5",
},
}
Please help me how to access all values ("-Lhdfgkjd6fn3AA-" , firstname, lastname, email and favQuote) into variables like: data.firstName, data.lastName, data.key, etc . Thank you.
let data = {
"-Lhdfgkjd6fn3AA-": {
"email": "t5#gmail.com",
"favQuote": "this is it",
"firstName": "t5",
"lastName": "l5",
},
};
console.log(Object.keys(data))//returning an array of keys, in this case ["-Lhdfgkjd6fn3AA-"]
console.log(Object.keys(data)[0])
console.log(Object.values(data))//returning an array of values of property
console.log(Object.values(data)[0].email)
Do need to be careful that the above code with the hardcoded "0" as index because it assumed that your data object has only one key. If you have more key, you can't simply replace index either because property of object has no predictable sequence
It's really a JavaScript question. I had to figure this out too. ...this works.
var p;
var thisLine;
p = docu.data();
for (var k in p) {
if (p.hasOwnProperty(k)) {
if (isObject(p[k])) {
thisLine = p[k];
Object.keys(thisLine).forEach(function (key, index) {
console.log(key, index);
});
}
}
}
function isObject(obj) {
return obj === Object(obj);
}
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So your first step is that you need to loop over the snapshot in your on() callback.
The second step is that you need to call Snapshot.val() to get the JSON data from the snapshot. From there you can get the individual properties.
firebase.database().ref('/users').orderByChild('email').equalTo(userEmail).on('value', snapshot => {
snapshot.forEach(userSnapshot => {
let data = userSnapshot.val();
console.log('data: ', data);
console.log(data.email, data.firstname);
});
})

Accessing Firebase data in a node with JS

So I have an object being returned from Firebase that looks like this:
{key: {name: "test", email: "test", id: "test"}}
How can I get the id out of this object?
If I do returnItem I get that object, so I tried to do returnItem[0] but it's not an array, and I've tried (Object.keys(tempSnap) but that just gives me the key not the object inside it.
This is my current code:
export function sendInvitation(email) {
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
let tempSnap = snapshot.val();
if(tempSnap != null) {
console.log(tempSnap);
}
});
return dispatch => firebaseRef.database().ref(`${userID}/invites`).push("This is a test Message!");
}
This is what it outputs:
Help would be awesome :D
If you already know id and it's a literal, then it's a matter of returnItem.id.
If you already know id and it's a variable, then it's returnItem[id].
If you don't know the keys and want to print all keys and their values, it's:
Object.keys(returnItem).forEach(function(key) {
console.log(key, returnItem[key]);
});
Update
Your new code shows the problem. When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result. Your callback needs to handle the fact that it gets a list by looping over the results with snapshot.forEach():
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
snapshot.forEach(function(child) {
let tempSnap = child.val();
console.log(tempSnap);
});
});
Try this:
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
snapshot.forEach(function(child) {
let keys=child.key;
let ids=child.val().id;
)};
)};
you have:
users
keyid
email:email
name:yourname
id: test

How to update Array field?

Im using Firebase Firestore and want to update an array field under a userprofile with the latest chat thread's id.. Im guessing that I have to pull the entire array (if it exists) from the chat node under that user, then I need to append the new id (if it doesnt exist) and update the array.. It works when theres only 1 value in the array then it fails after that with the following error:
Transaction failed: { Error: Cannot convert an array value in an array value.
at /user_code/node_modules/firebase-admin/node_modules/grpc/src/node/src/client.js:554:15 code: 3, metadata: Metadata { _internal_repr: {} } }
and here is my firebase cloud function, can anyone tell me where im going wrong ?
exports.updateMessages = functions.firestore.document('messages/{messageId}/conversation/{msgkey}').onCreate( (event) => {
/// console.log('function started');
const messagePayload = event.data.data();
const userA = messagePayload.userA;
const userB = messagePayload.userB;
// console.log("userA " + userA);
// console.log("userB " + userB);
// console.log("messagePayload " + JSON.stringify(messagePayload, null, 2) );
const sfDocRef = admin.firestore().doc(`users/${userB}`);
return admin.firestore().runTransaction( (transaction) => {
return transaction.get(sfDocRef).then( (sfDoc) => {
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
transaction.update(sfDocRef, { chats: array } );
});
}).then( () => {
console.log("Transaction successfully committed!");
}).catch( (error) => {
console.log("Transaction failed: ", error);
});
});
You're nesting arrays in your code here:
const array = [];
array.push(...[event.params.messageId, sfDoc.get('chats') ]);
This leads to an array with two values, the first one being the new messageId and the second value contains an array all of your previous values, e.g.
[ "new message id", ["previous id", "older id"] ]
This type of nested array is something that Firestore (apparently) doesn't allow to be stored.
The solution is simple:
const array = [event.params.messageId, ...sfDoc.get('chats')];
The fact that you have to first load the array to then add a single element to it is one of reasons Firebasers recommend not storing data in arrays. Your current data looks like it'd be better off as a set, as shown in the Firestore documenation:
{
"new message id": true,
"previous id": true,
"older id": true
}
That way adding a chat ID is as simple as:
sfDocRef.update({ "chats."+event.params.messageId, true })
I have looked further into the matter, and I would follow the advice that Frank gave you in his post; allocate the data in collections rather than with arrays as they have greater versatility for Firebase 1. Researching under the examples listed in the Firebase website looking for anything related to a chat, I’ve found the data structure and code for messages that are used by Firechat as they might be of use for you.
In the source code, they use a collection for the their message-id -userId pair with the following topology 2 :
The exact way how the saving is executed at the repository is 3 :
It executes an append of the message into the Room-id collection. Instead of this structure, you could use an userID - messageID pair as it might fit you better.

Categories

Resources