Reputation: 247
I'm currently trying to implement private chat messaging in my Angualar2 application. Currently I'm using AngularFire2 to work with a firebase. My Messages got a structure like:
Messages
message_id_0
from: user_id_0
to: user_id_1
type: "private"
message: "a private message"
But currently I can only select messages from one user_id.
this.af.database.list('messages', {
query: {
orderBy: "from",
equalTo: auth.uid,
...
So my questions is, how to select all messages with "from" field name for user_1 and user_2 ? Since Firebase doesn't support WHERE clause, its a challenge for me(
Upvotes: 0
Views: 690
Reputation: 9411
If I understand correctly, you want to show one user, e.g. Jim, all the messages between Jim and a particular other user, e.g. Sharon. The easiest way is to create a new field in the data.
Messages
message_id_0
from: user_id_0
to: user_id_1
fromTo: user_id_0 * user_id_0 // <------- added field
type: "private"
message: "a private message"
// e.g. An example dataset might be:
Messages
message_id: 5903784520934857403
from: Jim
to: Sharon
fromTo: Jim*Sharon
type: "private"
message: "whatever"
Then you can use your angularfire snippet, but orderBy the fromTo field.
It is worth using a separator (here I have used an asterisk) between the userIds, because if you don't, there could be an unintended collision, for example these two different pairs of users would have the same fromTo value:
from: chris
to: topher
fromTo: christopher
from: christ
to: opher
fromTo: christopher
If they have a separator character, such as "*", then the fromTo's become different. Make sure to use a character that cannot occur in a userId.
If you need to pick up messages that go in the reverse direction also (i.e. Sharon to Jim), I can think of two solutions:
This can obviously be extended to include an extra field for every combination you might wish to search or sort on.
The logical place in the program to create these extra fields is at the place a message is created. In your example question, the fields you chose to index on are ones whose values cannot change after they are created.
Readers wanting to use this approach for fields whose values can change, will probably want to make the code that creates these extra fields into a function that can be called whenever the raw fields are created or may have been edited.
Yes. That policy, of Normalization, is from an era when data storage was more expensive, and people were willing to wait for a computer to process multiple tables to spit out an answer. Now data storage, for the type of task you describe, is trivially cheap, and people want quick responses. So in Firebase and other NoSQL databases we are happy to Denormalize data where this helps a time-critical task.
One final warning: the second big benefit of Normalization was that if each data item, e.g. the message "from" field, is only stored once, there is no chance that our software might accidentally only update one copy and not the other. Therefore when we denormalize the database, as I described in this answer, we must be absolutely rigorous in making certain that all the extra fields (here the just the fromTo and fromToSorted fields) are updated whenever from or to are updated.
Upvotes: 2