Access the second item in Collection [Map] - javascript

I'm making a discord bot, and fetching some messages. I got this object
//This parameters changue every time i fetch
Collection(3) [Map] {
'848689862764789770' => Message {...
}
'848689552410804234' => Message {...
}
'848689534485004319' => Message {...
}
I can access the first and third entry using .first() and .last().
I've been trying to use Object.keys() but it returns undefined.
const mensajes = await message.channel.messages.fetch({ limit: 3 });
console.log(mensajes[Object.keys(mensajes)[1]])

Tip:
.first() can take a parameter that will return the first x amount of entries you choose and will then convert the Collection into an Array. Do .first(2) - this will return the first 2 entries - and then access the 2nd element as you would with any other Array.
// Will return 2nd entry
<Collection>.first(2)[1]
Suggested Solution:
You can also call .array() on the Collection to directly convert it into an Array.
// Also returns 2nd entry
<Collection>.array()[1]
<Collection> is a placeholder for your actual object
Learn more about working with Collections in This Guide

DiscordJS's docs has some information on this. You can transform this Collection utility class intro an array with a bunch of methods that exist for it, depending on what you need to access.
Then you can use the array, for example, to access the specific value.
// For values. Array.from(collection.values());
// For keys. Array.from(collection.keys());
// For [key, value] pairs. Array.from(collection);

Related

How to query an array on a db firestore?

I don't think I'm very far from the answer, I tried to query an id inside an array on Firestore.
I wanna compare the id of the participants.
Also my DB in Firestore:
And also my function, for the moment my function return size =0 so they can't catch the query.
const deleteAbuse = (type) => {
const participants = channel?.otherParticipants;
if (!participants || participants.length != 1) {
return;
}
const myID = currentUser.id;
const otherUserID = participants[0].id;
console.log('id user', otherUserID);
channelDB
.where('participants.id', '==', otherUserID)
.get()
.then((querySnapshot) => {
console.log(querySnapshot.size);
querySnapshot.forEach((doc) => {
console.log(doc.ref);
//doc.ref.delete();
});
});
};
There is no way you can query filter your "channels" collection to get documents based only on a single field of an object that exists inside the participants array. In other words, you cannot create that filtering based only on that ID. To be able to filter the data, you should pass to the where() function, the entire object, and not only some partial data. The object should contain values for all the fields. Only the ID is not enough.
And also my function, for the moment my function return size =0
That's the expected behavior since in your array there isn't any object that holds only a single field called id. All objects hold 7 fields, or even more than that, as I cannot see all fields in your screenshot.
I wrote an article called:
How to update an array of objects in Firestore?
Where you can find in the first part, the simplest way to get a custom object from an array of custom objects.
Alternatively, you can create an array that can hold only the IDs of the participants, filter the documents and create another database call to get their corresponding data.

adding elements to array and then returning the value after forEach loop

I am supposed to access a subcollection called 'followers' for a mobile user, this contains the id of the follower.
Using this ID i should get data about the follower from the mobile_user collection and add it to an array.
I can successfully iterate through the list of documents but when using push it seems like i'm unable to return the full list of data back out of the for loop.
Have a look at my current code:
Notice the two console logs, on the first one i can see the array getting filled with the information i want, on the second one the array it's returned empty. I'm definitely missing whatever is needed for the array to be returned out of the for loop.
I am fairly new to js and any advice in the right direction would be appreciated.
const getFollowers = (data, context) => {
let id = data.id
const mobileUserRef = db.collection('mobile_user')
return mobileUserRef.doc(id).collection('followers')
.get()
.then(function(doc) {
var result = []
doc.forEach(function(follower) {
mobileUserRef.doc(follower.id).get()
.then(function(followerdoc) {
result.push({
name: followerdoc.data().name
})
console.log(result)
})
})
console.log(result)
return result
})
}
mobileUserRef.doc(follower.id).get() is asynchronous and returns immediately with a promise. The forEach loop will not wait for that promise to resolve before moving to the snapshot in the list. You should instead push that promise into an array, then use Promise.all on that array to wait for all the gets to complete before moving on. Then you will have to iterate each of those results and push them into another array to give to the caller.
See also:
How to use promise in forEach loop of array to populate an object
Node JS Promise.all and forEach

Indexing into mongoose.model for an array is returning undefined

I've created a simple table (document?) in mongoDB.
I'm using Node and Mongoose to connect to it.
In my method, I am calling model.find({}) to retrieve all records and then iterating over them to find one that I want (this is within a loop - I'm thinking it will be more efficient to hit the DB once, and then process in memory to avoid connecting to the database each time).
When I console.log the match, I'm getting the full object printed out. When I print out one property, however, it's listing it as undefined. This property is an array, and it's happening for another property that has an array that I added as a test. What am I missing here?
Here's my code snippet:
Documents.find({}).then(docsData => { // Documents is my model
docs.entries.forEach(entry => { // docs.entries is the collection I want to match to
const match = docsData.find(
doc => doc['dropboxId'] == entry['id']
);
if (match) {
entry['tags'] = match.tags;
console.log('match tags', match.tags); // this prints out undefined
console.log('match', match); // this prints out the object with tags
}
Any ideas?
match is a Mongoose document which is different from normal JS object. I guess you need to do:
entry['tags'] = match.get('tags');

How To Efficiently Extract Certain Information From A POJO

I am working a lot with firebase, and am trying to load certain information from the database. The original data comes from a query, and is returned to me in a POJO. The console prints this when the original data is returned:
-KhQ76OEK_848CkIFhAq: "-JhQ76OEK_848CkIFhAq"
-OhQ76OEK_848CkIFhAq: "-LhQ76OEK_848CkIFhAq"
What I need to do is grab each of the values (-JhQ76OEK_848CkIFhAq and -LhQ76OEK_848CkIFhAq) separately, and query the real-time database again for each one. I can manage that aspect, but I cannot seem to figure out how to separate the values.
I have already tried to get a single output by doing:
console.log(vals[0]) but it just returned undefined, and splitting the string by " would be very inefficient for large data sets. Any ideas?
To access the values, you can iterate the snapshot's children using the snapshot's forEach method. The keys and values of the children can be obtained using the key property and the val() method:
firebase.database()
.ref("some/path")
.once("value")
.then((snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key); // The child's key: e.g. "-KhQ76OEK_848CkIFhAq"
console.log(childSnapshot.val()); // The child's value: e.g. "-JhQ76OEK_848CkIFhAq"
});
});
To solve this issue, all I did was convert the object returned into an array by using this code below:
var Array = Object.keys(datalist).map(function(k) { return datalist[k] });
Works like a charm, and I can now run a simple for loop for Array

How do I asynchronously query an API on an array of objects and then mutate each object correctly? (Using promises correctly)

I have an array of movies with IDs, but without ratings. I want to query a movie database to get the ratings for each movie, so I iterate over each object using fetch(url) to query the API and then use .then(function(response) { add_rating_to_specific_movie}).
The problem is, .then is an async response, and I have no way of knowing which movie has returned a rating value so that I can mutate the correct movie object with the rating. And I can't create a new array with the returned values, because some movies will return status: movies not found, and I have no way of knowing which movies are unrated.
Could use some guidance on a good algorithm for using promises here. Thanks!
You don't show your actual code for how you are iterating the array of movies so we can only provide a conceptual answer (next time show your actual iteration code please). But, in concept, you just use a function to pass the index or object separately for each array element and then you can access that index or object in the .then() handler. In this case, if you use .forEach() to iterate your array, the object from your array of objects that you are iterating and the index of that object are both passed to you in a function that will be uniquely available for each separate request.
For example, here's one concept that would work:
var movies = [....]; // array of movie objects
movies.forEach(function(movie, index) {
// construct url for this movie
fetch(movieURL).then(function(data) {
// use the data to set the rating on movie
movie.rating = ...
});
});
If you want to use promises to know when all the requests are done, you can do this using Promise.all():
var movies = [....]; // array of movie objects
Promise.all(movies.map(function(movie, index) {
// construct url for this movie
return fetch(movieURL).then(function(data) {
// use the data to set the rating on movie
movie.rating = ...
});
})).then(function() {
// all ratings updated now
});

Categories

Resources