Search with array in firebase realtime database - javascript

Is there any way to search with array in realtime database as cloud database provides us.
Cloud example:
.collection("bids")
.where("title", "array-contains-any", ["xx", "yy", "zz"])
In above query I got all bids where title is xx, yy, zz.
How do we can search like this in firebase realtime database.

Actually in real-time database there is no any thing like "array-contains". There for if you have an array you have to deal with just like a regular JavaScript array.
In your case you can try this.
var ref = firebase.database().ref('/bids/title');
ref.once('value').then(function(snap) {
var array = snap.val();
for (var i in array) {
var value = array[i]
console.log(value);
if (value == 'xx') { ... }
}
});

There is no equivalent operation in the Realtime Database.
The common approach for this type of use-case, is to set up an additional data structure mapping from bid titles to bids as shown here: Firebase query if child of child contains a value
You can then read the bid IDs for each title with a separate query, look up the additional properties for each bid with another call, and then merge all results in your client-side application code. This is not nearly as slow as you may initially expect, as Firebase pipelines the requests over a single websocket connection.

Nowadays, in Firebase's real-time database, you don't have to do that anymore! These ugly codes to save arrays nowadays are left behind, try to use the module: Fireray.
These codes make Firebase references very ugly, for example:
"dir": {
"arrays": {
"users": {
"0": {},
"1": {},
"2": {}
}
},
"others": {}
}
It is a Brazilian module, but there is a documentation in English. Give her a chance, she's really very good!
Links:
Npm package
Documentation in English
Repository
Programmer
Sincerely: Lucas

Related

read messages from realtime databse in firebase with javascript

i want to read messagea from realtime database in firebase with vue or javascript in quasar framework
my collection name in db is messages that have this strtucture:
******************************************* my db structure*******
messages
-N4zbIt0Ey6Bix54f5SE
content: "Hi"
fromId: "nTTcnND2y6OHUBVO2GxHoBFwQf32"
timestamp: 1655703420767
toId: "0FXpksPdL4OAf9KAXx9B0R6nzmh2"
type: 1
-N4zbIt0Ey6Bix54f5SE
content: "Hi,HOW ARE YOU"
fromId: "0FXpksPdL4OAf9KAXx9B0R6nzmh2"
timestamp: 1655703448111
toId: "nTTcnND2y6OHUBVO2GxHoBFwQf32"
type: 1
do you know how i query firebase to getmessages?? ithis is for save in state with Vuex
firebaseGetMessages({ commit, state }, otherUserId) {
let userId = state.userDetails.userId
messagesRef = firebaseDb.ref('messages/' + fromId + '/' + toId)
messagesRef.on('child_added', snapshot => {
let messageDetails = snapshot.val()
let messageId = snapshot.key
commit('addMessage', {
messageId,
messageDetails
})
})
i think this code is wrong
please help me if you have any experince with firebase
i am not familar with realtime-databse and query in fcm
but familar with mongodb and sql server database
i think that firebase has some function to read message!!! is it n't???
Your code indeed does not match the data structure that you shared.
Your code expects this structure:
messages: {
"uidOfSender": {
"uidOfRecipient": {
...
}
}
}
While your data structure has the UIDs of the sender and receiver as properties on each message in a flat list.
Worse: there is no way to get the messages between a sender and receiver from your current structure, as Firebase Realtime Database queries can only filter on one property. See my answer here for more on that: Query based on multiple where clauses in Firebase
The data structure in general looks like a 1:1 translation of what you'd do in a relation database, which is often not a great starting point when modeling data for a NoSQL database. What you'll want to do is create a different data structure where you set up a sort-of "chat room" for each pair of users, as I've shown here: Best way to manage Chat channels in Firebase
I also recommend reading NoSQL data modeling and watching Firebase for SQL developers.

Query stored values that contain specific string

I have a small realtime firebase database that's set up like this:
database
-messages
--XXXXXXXXXXXX
---id : "XXX-XXX"
---content : "Hello world!"
It's a very simple message system, the id field is basically a combination of users id from my mysql database. I'm trying to return all messages that match one of the ids, either sender or receiver. But I can't do it, seems like firebase only support exacts querys. Could you give me some guidanse?
Here's the code I'm working with
firebase.database().ref("messages").orderByChild("id").equalTo(userId).on("value", function(snapshot)
I'm looking for something like ".contains(userId)"
Firebase supports exact matches (with equalTo) and so-called prefix queries where the value starts with a certain value (by combining startAt and endAt). It does not support querying for values that end with a certain value.
I recommend keeping a mapping from each user IDs to their messages nodes, somewhere separately in their database.
So say that you have:
messages: {
"XXXXXXXXXXXX": {
id : "YYY-ZZZ",
content : "Hello world!"
}
}
You also have the following mappings:
userMessages: {
"YYY": {
"XXXXXXXXXXXX": true
},
"ZZZ": {
"XXXXXXXXXXXX": true
}
}
Now with this information you can look up the messages for each user based on their ID.
For more on the modeling of this type of data, I recommend:
Best way to manage Chat channels in Firebase
Many to Many relationship in Firebase
this artcle on NoSQL data modeling

How to add indexOn a userId in firebase database

i am getting an error of
Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "WkJymEhTtvgtIzQZZxs3VUTbmLh2quan" at /Products to your security rules for better performance.
this is my code:
firebase.database().ref("Products").orderByChild(user.uid + "quan").startAt(0).on('value', function (s) {
var cartNum = 0;
s.forEach(function (d) {
console.log(d.child(user.uid + "quan").val());
cartNum += d.child(user.uid + "quan").val();
});
$("#cartCount").text(cartNum);
});
am trying to query products that has user.uid+ 'quan' in my firebase database
and this is the structure of my JSON ---->>>
many thanks if someone can help me out
As described in the documentation on indexing data and in the error message, you will need to add an index to the Firebase rules for your database in the console:
{
"rules": {
"Products": {
".indexOn": "WkJymEhTtvgtIzQZZxs3VUTbmLh2quan"
}
}
}
This will solve the error message for the current user. The problem is that you will need to declare such an index explicitly for each UID, which is not feasible unless you have a specific set of users in mind.
The underlying problem is that your current data structure makes it easy to find a user for a given product, but it does not make it easy to find the products for a specific user. To allow the latter use-case, you'll want to add an additional data structure for that inverted mapping, sometimes referred to as a reverse or inverted index:
"Users": {
"uid1": {
"productId1": true,
"productId2": true
},
"uid2": {
"productId3": true,
"productId4": true
}
}
While this duplicates some data, it allows you to look up the related data in both directions. This type of data duplication to allow use-cases is quite common in NoSQL databases.
Also see:
Many to Many relationship in Firebase
Firebase Query Double Nested
Firebase query if child of child contains a value

How best can I retrieve all comments for a given chat room in Firebase on the web?

I have a real time firebase app with chatrooms and comments. A comment belongs to a single chatroom and a chatroom can have many comments. I'd like retrieve just the comments for a given room, but right now I'm only able to get all of them.
Every time a comment is saved, I also save its id to the room to which it belongs. That way, every room has a list of its comment ids. I can retrieve a chatroom's list of child comment ids using chatRooms/${id}/commentIds.
// data structure is basically like this:
chatRooms: {
ROOMID123: {
title: "Room A",
commentIds: {
COMMENTIDABC: true,
COMMENTIDXYZ: true
}
}
},
comments: {
COMMENTIDABC: {
message: "some message",
parentRoomId: ROOMID123
},
COMMENTIDXYZ: {
message: "Another message",
parentRoomId: ROOMID123
}
}
I can get the comment ids for a given room, based on the room's id, like this:
firebase.database().ref(`chatRooms/${chatRoomId}/commentIds`).on('value',
snapshot => {
const commentsObject = snapshot.val();
const commentIdsList = Object.keys(commentsObject);
});
Would it be better for me to
a) use that list of commentIds to retrieve only the comments for a given room? If so, what query should I use?
b) use the chatRoom's id to retrieve every comment with a matching parentRoomId? If so, I don't know how to do this despite reading through the docs.
Thank you!
I'd propose a third option: store the comments for each chat room in a separate parent node. So something like:
commentsPerRoom: {
ROOMID123: {
COMMENTIDABC: {
message: "some message",
},
COMMENTIDXYZ: {
message: "Another message",
}
}
}
With the above structure you can retrieve the comments for a specific room with a single direct lookup:
firebase.database().ref(`commentsPerRoom/${chatRoomId}`).on('value',
Reasons I'd use this data structure over your current one:
Storing the comments as a single list means you'd have to query that list. And while Firebase Realtime Database scales quite well, querying for data is always going to have scalability limits. That's why the above data structure allows a direct look up, instead of requiring a query.
Loading the individual comments through the comment IDs is definitely also possible, and not nearly as slow as some developers think due to the fact that Firebase pipelines the requests over a single connection. But it seems unneeded here, since the comments already have a strong 1:n association with the room they belong to. Each comment only belongs to one room, so you might as well model that relationship in how you structure the data, and save yourself all the lookups.
Retrieving comments for a specific room is by far the most common use-case, and this data structure allows that use-case the most efficiently.

Querying By Multiple Keys in Firebase

I have a list of known keys in my Firebase database
-Ke1uhoT3gpHR_VsehIv
-Ke8qAECkZC9ygGW3dEJ
-Ke8qMU7OEfUnuXSlhhl
Rather than looping through each of these keys to fetch a snapshot of their respective object, how can I query for each of these keys in one single, unified request? Does Firebase provide this?
I've discovered the Promise.all() function which looks promising (no pun intended I swear) but I'm not sure how to implement it using the standard way of fetching firebase data like so
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
});
Thanks for any help!
As David's comment suggested: if the items are in some way related, you may be able to built a query to get them all.
Otherwise this would do the trick:
var keys = [
"-Ke1uhoT3gpHR_VsehIv",
"-Ke8qAECkZC9ygGW3dEJ",
"-Ke8qMU7OEfUnuXSlhhl"
];
var promises = keys.map(function(key) {
return firebase.database().ref("/items/").child(key).once("value");
});
Promise.all(promises).then(function(snapshots) {
snapshots.forEach(function(snapshot) {
console.log(snapshot.key+": "+snapshot.val());
});
});
Note that retrieving each item with a separate request is not as slow as you may think, since the requests are all sent over a single connection. For a longer explanation of that, see Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly.

Categories