array-contains not fetching result in 2 Dimensional array - javascript

I am saving data in a Document like the below image. I want to fetch the records from array notifyArray , ctg where array-contains Burger.
This is the code i am trying :
firebase.firestore().collection(`notifications`)
.where("notifyArray", "array-contains", 'Burger')
.onSnapshot(querySnapshot=> {
querySnapshot.forEach(doc=> {
console.log(doc.data());
console.log("Search result");
var data = Object.assign(doc.data(), {docid : doc.id})
this.goalList1.push(data);
});
console.log(this.goalList1);
});
But it is not returning any result. Ideally it should return 2 records.

The array notifyArray is an array of maps, each map containing two properties. Firestore doesn't support querying of map properties in an array. You can only search for the entire contents of the map, which means you have to know all of the values of all of its fields.
What you can do instead is make a new array that contains only the string values of the food property in the map, then query that array instead.
firebase.firestore()
.collection(`notifications`)
.where("foodArray", "array-contains", 'Burger')
Above, the query is expecting that there is an array of strings called foodArray.

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.

Access the second item in Collection [Map]

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

Firestore where query with parameter not working

I have a query that is not working as I expect it to. I have a collection called 'games' that has a number of documents in it.
Each document has an array called 'hiScores' that consists of the results from that round. I would like to query all games for a specific player for example:
.where('hiScores.playerName', '==', 'David Lamm')
This is not returning anything. I have no problems when querying a top level variable in the document. What have I done wrong?
Database:
db.collection('games')
.where('hiScores.playerName', '==', 'David Lamm')
.get()
.then(function(querySnapshot) {
console.log('Davids games:')
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
}
);
The problem is that the hiScores field is an array, not an object. You can tell it's an array because the first immediate element of the array in the screenshot has index 0. You're trying to query hiScores as if it's a single object with a single property called playerName.
Firestore doesn't support querying for object properties within within array fields. If you have an array field, you can only query to find documents where an entire item is present in the array (an arrayContains query).
As pointed out by Doug this is currently not possible in firestore.
You can create a top level array of strings in each game named playerNames[]. Then use the where condition on playerNames with array_contains.

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