how to get items from array on respectively - javascript

I have an array contain unique keys, these keys I want to take it to get his Data from firebase real-time DB
the array like this
["dtnMG3dVEQXL1TPct3awl927jax2", "y5eAQppoEZRELsDL3hLbY5b0A763"]
so I iterate it using forEach Method to get a single key to check if found in the users tree or not But the result is null?
But when I Log the keys.forEach(key => console.log(key)) I can Get every key in a single line
firebase
.database()
.ref("users")
.child(keys.forEach(key => key))
.once("value")
.then(users => {
// let username = users.val().username;
console.log(users.val());
// Object.assign(users, { [Object.keys(users)]: username });
});
Edit
So thats fine and get every single username, Now the new issues is i want to save these names to other object i have
users = {
dtnMG3dVEQXL1TPct3awl927jax2: // the unique key
-LmUSeyWtBPqcoN8l6fd: [{…}]
-LmUgcbdzElxWpLkN-F9: [{…}]
// here's i want to add somthing like thies
-username : "userOne" //I got it from the Looping
y5eAQppoEZRELsDL3hLbY5b0A763:
-LmSTYlxa7bjy0Beazmy: [{…}]
-LmUad3lvkPdTQDFo4Ds: [{…}]
-LmUyDmGcEmYKOJnvEiA: [{…}]
// here's i want to add somthing like thies
-username : "userTwo" // I got it from the Looping
}

keys.forEach(key => key)
This return every element of the array keys. And you are passing these elements to the child function. However, child functions expects only one argument.
Try this:
for( let key of keys){
firebase
.database()
.ref("users")
.child(key)
.once("value")
.then(users => {
// let username = users.val().username;
console.log(users.val());
// Object.assign(users, { [Object.keys(users)]: username });
});
}
Side not: Do not call async function inside forEach loop.

.child(keys.forEach(key => key)) - This is your problem. This forEach effectively returns all your array values one by one. But you call it inside a function with one argument that gets called one time. So it will only check for the first value in your array and the rest will be dumped, so its like looking inside a 1-element array.
Solution is to perform the DB calls inside the iteration:
keys.forEach( key => {
firebase
.database()
.ref("users")
.child(key)
.once("value")
.then(users => {
// let username = users.val().username;
console.log(users.val());
// Object.assign(users, { [Object.keys(users)]: username });
}});
EDIT:
to do what you wanted after you edited, assuming the variable curUser holds the username you want to insert and curKey is the key associated to that username, just: users[key]["username"] = curUser;. This will reference the property which is named after curKey in the users object, and will create a "username" property in it and store the value there.
Notice that if you already have "username" property in this key object it will be overriden.
** I assumed the data structure of the key-properties inside "users" are objects even tho your code doen't really show it.

Related

Unable to add object fetched from mongoDB to normal javascript array

I am trying to create an add to cart button which fetches the data from product database using the id of specific product which I selected. I am trying to push the object found using the same Id into a normal javascript array and then to display it using ejs methods. While I was tring I found I am unable to push the data in object form.
Summary:
On 7th line I have declared an array and in that array I want to store some objects which I have fetched frome a db model.
On 15th line I am trying to push the object form into my array so that I could iterate through the objects to display them on my page using ejs. But I am unable to do that.
screenshots:
Here's the final result I'm getting even after trying to push objects in array:
empty array logged
Here are the objects I'm trying to push:
Objects
Code:
app.get("/cart", (req, res) => {
if (req.isAuthenticated()) {
const findcartdata = req.user.username;
userData.findOne({email: findcartdata}, (err, BookId) => {
// console.log(BookId.cartItemId);
const idArray = BookId.cartItemId;
var bookArray = [];
idArray.forEach((data) => {
productData.findOne({_id: data}, (err, foundBookData) =>{
// console.log(foundBookData);
if(err){
console.log(err);
}
else{
bookArray.push(foundBookData);
}
})
});
console.log(bookArray);
// res.render("cart", {
// cartBookArray: BookId.cartItemId
// })
});
} else {
res.redirect("/login");
}
})
In above code i found the user's email using passport authentication user method and using that email I wanted to add the products in a different javascript array (which I am goint to pass to my ejs file of cart and then iterate it on list) using those array of Id which I got from another model called userData. The problem is I am able to find userData of each Id but unable to store them as an array of objects.
Looks like a timing issue, your code completes before the database downloads the objects and pushes them to your array.
This should fix your issue:
// ...
const idArray = BookId.cartItemId;
var bookArray = [];
for (const data of idArray) {
const foundBookData = await productData.findOne({_id: data}).catch(console.error);
if (!foundBookData) continue;
bookArray.push(foundBookData);
}
console.log(bookArray);
// ...
By the way, make sure to make the whole function asynchronous as well, which would be done by changing this line:
userData.findOne({email: findcartdata}, async (err, BookId) => { // ...

How do I change an object's value in an IndexedDB index?

Is it possible to update an object's value within an IndexedDB index without cloning, deleting, or putting a new entry? Theoretically something like the following snippet would do the trick, though it probably would not delete until the put was confirmed. But it looks like overkill to me. It looks like it would be a nightmare to do any error handling on.
const objectStore = db.transaction([objectStoreName], 'readwrite')
.objectStore(objectStoreName);
const requestGet = objectStore.get(index);
requestGet.onsuccess = (event: any) => {
const value = event.target.result.value // Store old value
const requestDelete = objectStore.delete(index);
requestDelete.onsuccess = (event: any) => {
const requestPut = objectStore
.put({index: 'New Index Value', value: value}); // Put back using new index
};
};
You cannot directly change values in an object store's index. You can change the values of an object in an object store, and IndexedDB will propagate your changes to related indices. Indices are essentially read-only.
It is possible since you specify your index, otherwise, an other logic may be necessary.
As you should know, the IDBObjectStore has a method .put() which it will receive two params. With it you can either PUT a new value or UPDATE a value.
IDBObjectStore.put(item, key)
item: The item you want to put/update
key: opcional: Your primary object store key (such as an uuid, a random number, in short...) for that item you would like to update.
Code:
//This is an example only.
//Let's think that we have an object store into our IndexDB 'user', where object store is called by user-data:
//# Key Value
//0 1 { username: 'John Doe' }
//Here, we are receiving the 'success' result from an indexedDB.open(), and using its result with a promise.
dbPromise.then(db => {
//Getting the transaction
const transaction = db.transaction('user-data', 'readwrite')
//Getting the objectStore with the data, the same object store before.
const store = transaction.objectStore('user-data')
//Getting the key's object store, in the other other words, this is the key you define when you create you objectStore, with createObjectStore. In this example, I've used 'autoIncrement: true'
const query = store.get(1)
//Getting the query result with a success listener.
query.addEventListener('success', event => {
const { ['result']: user } = event.target
user.productsIntoCart.push(newItem)
//With this, we will be able to change the object store value.
user.username = 'Jane Doe'
store.put(user, 1)
})
query.addEventListener('error', event => console.error(event))
transaction.addEventListener('complete', () => db.close())
})
//# Key Value
//0 1 { username: 'Jane Doe' }
You can see more details you want in the MDN IDBObjectStore.put documentation.
IDBObjectStore

Updating A Deeply nested Array of Objects inside a mongoose query

I am trying to update a mongoose document, But its a deeply nested array of objects and I am having trouble updating it using the spread operator. I have an array of image-links and I wanna iterate through the relationships array in the database and add an image to each relation. The code shows my approach, but the syntax is wrong. I have added a db image which shows where I wanna add the image variable.
// Get Images
const imagesData = await axios.get(
"https://randomuser.me/api/?results=4&gender=male"
);
const images = [];
imagesData.data.results.forEach((result) => {
images.push(result.picture.large);
});
// Update Company
for (let i = 0; i <= 3; i++) {
const updateCompany = await Companies.findByIdAndUpdate(
req.params.id,
{ relationships: [
...relationships,
relationships[i]: {
...relationships[i],
image: images[i]}
] },
{ new: true }
).exec();
}
Also I am using a mongoose query inside a for loop. Is it the right way to do it.
mognoDB
You should fetch the document that you want. Then treat the fetched object as a javascript object and add or update whatever you want then use .save() function provided by mongoose.
let result = await Companies.findById(id);
result = result.map((company)=>{
update your object here
})
result.save()
The .save() function will take care of updating the object in the database

onSnapshot, forEach, and get() synchronously on Firebase

I am using firebase's .onSnapshot to grab the ID of the users currently online, and store each ID to an array. I successfully deployed .onSnapshot to get the ID of the online users, but I return an empty array at the end
var learning_language;
db.collection(ll_profile).doc(user_uid).get().then(function(doc) {
learning_language = doc.data().learning_language;
})
db.collection(ns_status).where("state", "==", "online").onSnapshot(function(snapshot) {
var ns_match = [ ];
snapshot.forEach(function(userSnapshot) {
db.collection("ns_profile").doc(userSnapshot.id).get().then(function(doc) {
spoken_language = doc.data().spoken_language;
if (learning_language == spoken_language) {
ns_match.push(userSnapshot.id);
console.log(ns_match);
}
})
})
return (ns_match);
What I am trying to do is to first define the learning_language retrieved from the collection ll_profile with the current user's ID named user_uid.
Then .onSnapshot listens to another group of users' online state (which automatically updates if an user is online or offline) inside ns_status collection. After, the returned online user from .onSnapshot is checked if the spoken_language field inside their document (named with their corresponding uid) matches with learning_language defined earlier. If it matches, then store the uid into the array of ns_match.
The values inside ns_match are correct. I think .get() executes asynchronously. That is why ns_match is returned empty.
How should I return ns_match at the end with all the values stored properly?
Thanks in advance.
function getMatches() {
return new Promise(resolve => {
db.collection(ll_profile).doc(user_uid).get()
.then(function(doc) {
var learning_language = doc.data().learning_language;
db.collection(ns_status)
.where("state", "==", "online")
.onSnapshot(function(snapshot) {
var ns_match = [];
snapshot.forEach(function(userSnapshot) {
db.collection("ns_profile")
.doc(userSnapshot.id)
.get()
.then(function(doc) {
spoken_language = doc.data().spoken_language;
if (learning_language == spoken_language) {
ns_match.push(userSnapshot.id);
console.log(ns_match);
}
});
});
resolve(ns_match);
});
});
});
}
getMatches().then(ns_matches => console.log(ns_matches));
wrapping in a promise is the correct move. However, remember that snapshot returns metadata about your result. Particularly, snapshot.size. One can use that value to count records, inside the foreach method, or compare the destination array length with the snapshot.size value

Firebase Database: why do the key/ref in my queried datasnapshot refer to its parent?

I would like to delete an entry from the realtime database that i looked up through a query but i am getting unexpected results for both the ref and key properties.
ref('photos/users/USERID')
.orderByChild('photoname')
.equalTo('photoname i want to look up')
.limitToFirst(1)
.query('once')
.then(snapshot => {
// correct data at 'photos/users/USERID/PHOTOID'
const entry = snapshot.val();
// seems to be the ref to photos/users/USERID'
const ref = snapshot.ref;
// seems to be USERID
const key = snapshot.key
})
Why aren't these the ref/key to the entry i just found? And what is the best approach to remove this entry?
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 code needs to take this list into account, and iterate over snapshot.forEach() to get the actual matching item:
ref('photos/users/USERID')
.orderByChild('photoname')
.equalTo('photoname i want to look up')
.limitToFirst(1)
.query('once')
.then(snapshot => {
snapshot.forEach(child => {
const entry = child.val();
const ref = child.ref;
const key = child.key
});
})
Your ref and key are based on ref('photos/users/USERID'), not the filtered subset you have created. Is there any reason you wouldn't call ref('photos/users/USERID/PHOTOID')?

Categories

Resources