I've tried to find an answer about the following problem - found a couple in similar questions but cannot still solve it. If I flatten the structure it seems to work, but why?
basically - how do I add more key-value pairs in a json-object at Firebase WITHOUT owervriting existing ones?
let say I have the following jsonstructure
"groups" : {
"aw" : {
"members" : {
"Lisa" : "true"
},
"name" : "aw university"
}
}
How do I then add more key-value pairs in members without overwriting existing ones? For instance, I want to add one more member - Magnus so the object becomes:
"groups" : {
"aw" : {
"members" : {
"Lisa" : "true",
"Magnus" : "true"
},
"name" : "aw university"
}
}
I have tried with updateChildren without success:
var hm = HashMap<String, Any>()
hm.put("magnus", "true");
database.child("groups").child("aw").child("members").updateChildren(hm)
What happends is that existing key-value (Lisa: true) is overwritten
Is there a simple solution to this problem?
the strange thing is that if the structure is flattened - updateChildren works and adds Magnus
"groups" : {
"aw" : {
"name" : "aw university"
},
"members" : {
"Lisa" : "true",
"Magnus" : "true"
}
}
But I want "members" to be a child of "aw"
Try this database.child("groups").child("aw").child("members").setValue(hm);
Related
This is how my firebase real-time database looks like.
{
"users" : {
"PDFZ0QOoTxYbCyruOrbiA2y1n5O2" : {
"email" : "mark#outlook.com",
"name" : "Mark Evans",
"paymentMethods" : {
"-ML5oMsCnXgfBRCh7DdO" : {
"paymentProvider" : "Google Pay",
"phone" : "+915555555555",
"userName" : "Mark Evans"
},
"-ML5oRHklHHIK33NQowD" : {
"paymentProvider" : "BHIM",
"phone" : "+911111111111",
"userName" : "Chris Evans"
}
},
"uid" : "PDFZ0QOoTxYbCyruOrbiA2y1n5O2"
},
"epyBsLU0fYOT8uc0Bo698f5SRcO2" : {
"email" : "axle#gmail.com",
"name" : "Axle Blaze",
"paymentMethods" : {
"-ML5o5Zv_3ZixCIXWBqg" : {
"paymentProvider" : "Google Pay",
"phone" : "+918888888888",
"userName" : "Axle Blaze"
},
"-ML5o9pMNucaacdU0G3P" : {
"paymentProvider" : "BHIM",
"phone" : "+911111111111",
"userName" : "Bunny Blaze"
}
},
"uid" : "epyBsLU0fYOT8uc0Bo698f5SRcO2"
}
}
}
I need to get those payment options where phone number = "+91XXXXXXXXXX" no matter from which user payment option belongs to.
For example: If i need all payment options where phone == +911111111111
Result should be :
"-ML5oRHklHHIK33NQowD" : {
"paymentProvider" : "BHIM",
"phone" : "+911111111111",
"userName" : "Chris Evans"
},
"-ML5o9pMNucaacdU0G3P" : {
"paymentProvider" : "BHIM",
"phone" : "+911111111111",
"userName" : "Bunny Blaze"
}
I have to do this in Android but since querying should be similar for any platform so I need help with how the query should be structured.
Any kind of help is appreciated. Thanks in advance.
Firebase queries work on a flat list. The value you order/filter on must be in a fixed location under each direct child node of users.
In your current structure, you can:
Search across all users for direct properties of that user, such as their email or name.
Search across the payment methods of a specific users.
The query you want is not possible on your current data structure. If you want to allow a query across all payment methods of all users, you'll need to change (or augment) your data structure to (also) have a flat list of payment methods across all users.
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value
This question already has answers here:
Query based on multiple where clauses in Firebase
(8 answers)
Closed 5 years ago.
Solution:
As Frank already states, I had to create a separate filed for this sorting to work. As suggested, I created a filed "sortField" which combines the
"clubKey" + "_" + "startDate"
To modify my existing data sets, I made a quick java script function like this:
function createTestDataSet(){
evd = dbAllEventsListRef;
evd.on('child_added', function(snap, previous){
console.log(snap.val());
data = snap.val();
data.sortField = data.clubKey + "_" + data.startDate;
testDiv = document.getElementById("divCarSummary");
testDiv.innerHTML = testDiv.innerHTML + "<br/>"+data.sortField;
evd.child(snap.key).set(data);
});
}
I tested this using the following code:
function testSort(){
key = "manualClubKey-1";
testEvents = dbTesting.child('eventList').orderByChild("sortField").startAt(key+"_").endAt(key+"a");
testEvents.on('child_added', function(snap, previous){
data = snap.val();
testDiv = document.getElementById("divCarSummary");
testDiv.innerHTML = testDiv.innerHTML + "<br/>"+data.startDate+", "+data.name+", "+snap.key+", "+data.clubKey;
console.log(snap.val());
});
}
The tricky part was, that the manual for "endAt" states:
The ending point is inclusive, so children with exactly the specified value will be included in the query
But this does not seem to be true.
If I give the same value for startAt() and endAt(), I get no results.
So I modified the query, that I look for the "clubKey" + the separator. For the Separator I gave a character right after the "_". thus it works like a charm.
I modified my android Code, so every time the startDate, or the clubKey is written, I update the "sortFiled", small change, works like a charm.
Original Question
I have some event data.
Sample data:
{
"modeltruckerManualEventID-96" : {
"canceled" : false,
"clubKey" : "manualClubKey-1",
"endTime" : "17:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-06-17",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-97" : {
"canceled" : false,
"clubKey" : "manualClubKey-2",
"endTime" : "17:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-06-17",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-98" : {
"canceled" : false,
"clubKey" : "manualClubKey-2",
"endTime" : "16:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-03-11",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-99" : {
"canceled" : false,
"clubKey" : "manualClubKey-1",
"endTime" : "16:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2011-11-27",
"startTime" : "10:00:00"
}
}
I now want to filter, so I only get events from one "clubKey"
which I could achieve using:
.orderByChild("clubKey").equalTo("manualClubKey-1")
That works fine.
But is there any way, that I can order the results also by child "startDate"?
So I want to have the filtered results ordered by startDate finally.
As far as I know this does not work.
I use Firebase on Android with Firebase UI.
Any Ideas how to achieve that?
I do not want to restructure the data or duplicate it further.
Hope there is a way, maybe force the ordering already on storage?
If you want to orderByChild(especificdate), is not possible without restructuring the data.
However, lets say you want to get the latest added nodes, just use limitToLast(numberOfChildren)
I'm a newbie working on an Android project using Firebase v3.
I have set up a data structure that relates stores to brands as follows:
stores -> [brandId] -> [storeId] -> store object
"stores" : {
"1z05cQF7FnWkCTe2KC9eqCHi6Ji2" : {
"hSlKozrMq2aNGQqWDZ7eU2UzNtr1" : {
"brid" : "1z05cQF7FnWkCTe2KC9eqCHi6Ji2",
"email" : "di#cof.ci",
"uid" : "hSlKozrMq2aNGQqWDZ7eU2UzNtr1"
}
},
"LqZ81PF7bKXPtoASWUWMQKFYMK62" : {
"-Kidnq4rlssa5d1Ic8gv" : {
"brid" : "LqZ81PF7bKXPtoASWUWMQKFYMK62",
"email" : "test#test.test",
"uid" : "-Kidnq4rlssa5d1Ic8gv"
}
},
}
I would like without knowing the brandId to get the store object.
Is that possible?
I tried using orderByChild and orderByKey but nothing seems to work, either everything is returned or null.
e.g.
var tellerRef = firebase.database().ref('/stores/');
tellerRef.orderByChild(uid).once('value').then((snapshot) => console.log(snapshot.val()));
where uid = "hSlKozrMq2aNGQqWDZ7eU2UzNtr1" returns everything!
I have a list of all the keys I want to download from Firebase. For this I'm using this code:
Query newUidsQuery = FirebaseDatabaseHelper.getUsersReference();
newUidsQuery.orderByChild(DATABASE_NODE_USER_UID);
for (String uid : uidList) {
newUidsQuery.equalTo(uid);
}
newUidsQuery.addListenerForSingleValueEvent();
This is my current structure:
{
"users" : {
"5mvsiNKz2hO4rmcDDNskv855dkB3" : {
"contacts" : [ "GG8JeRNOIhb1qloZb4oCAb7Jd593", "gc0ci7Jgu2QpVYFbeiMJfVy1WHP2" ],
"contactsHash" : -224276455,
"email" : "lung.razvan#yahoo.com",
"name" : "Razvan Cristian Lung",
"photoUrl" : "https://lh5.googleusercontent.com/-bItm3-ieAtU/AAAAAAAAAAI/AAAAAAAALZo/mtPyAMohOvg/s96-c/photo.jpg",
"uid" : "5mvsiNKz2hO4rmcDDNskv855dkB3"
},
"GG8JeRNOIhb1qloZb4oCAb7Jd593" : {
"contactsHash" : 1,
"email" : "andralung#yahoo.com",
"name" : "Andra Florina Lung",
"photoUrl" : "https://lh4.googleusercontent.com/-po2yelyi3mY/AAAAAAAAAAI/AAAAAAAAQ5s/ROefxP6Q1oA/s96-c/photo.jpg",
"uid" : "GG8JeRNOIhb1qloZb4oCAb7Jd593"
},
"gc0ci7Jgu2QpVYFbeiMJfVy1WHP2" : {
"contactsHash" : 1,
"email" : "lung_razvan2100#yahoo.com",
"name" : "Lung Razvan",
"photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p100x100/15390976_1192204140865562_3397773349261436244_n.jpg?oh=d61795a8df67d3e9c5ddf60557e9e60c&oe=59270863",
"uid" : "gc0ci7Jgu2QpVYFbeiMJfVy1WHP2"
}
}
}
The problem is that when I try to get only the entries with the specific key I also get the other entries that have that key as a value in the "contacts" field.
When you call orderBy... or other methods, it returns a new query. So you're now creating a new query for each uid that you then don't use. To keep it, you'd need newUidsQuery = newUidsQuery.equalTo(uid).
But that won't solve the problem yet, because a query can only order/filter on a single property and value. See Query based on multiple where clauses in firebase.
Better news is that this doesn't matter much here, since you can just retrieve the items one at a time. Unlike what you might expect, that's not significantly slower than retrieving them in one go. See Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly or watch this episode of #AskFirebase: https://youtu.be/66lDSYtyils?t=1m49s
I have two siblings namely "intents" and "messages". when I update the messages fields it gets done properly but one the same procedure is done with intents fields, no change occurs. Below is the android-java code for the same.
IntentMessage testIntentMessage = new IntentMessage("Hello test intent", "Hello test intent");
FriendlyMessage tempMessage = new FriendlyMessage("namastey", "india", "http://imgsdown.1mobile.com/group1/M00/C1/21/S36rZla-KYqAV08jAABUIgbzI-E596.png","543587653");
mFirebaseDatabaseReference.child("intents").child("-sjhfdvshv").setValue(testIntentMessage);
mFirebaseDatabaseReference.child("messages").child("-KUVR-MkLOVwNkx6nm-_").setValue(tempMessage);
Below is my firebase database JSON file after above commands are executed:
{
"intents" : {
"-kjuvhsjkv" : {
"intentFields" : "testIntentFields 1",
"intentName" : "testIntentName 2"
},
"-sjhfdvshv" : {
"intentFields" : "testIntentFields",
"intentName" : "testIntentName"
}
},
"messages" : {
"-KUVR-MkLOVwNkx6nm-_" : {
"name" : "india",
"photoUrl" : "http://imgsdown.1mobile.com/group1/M00/C1/21/S36rZla-KYqAV08jAABUIgbzI-E596.png",
"text" : "namastey",
"timeStamp" : "543587653"
}
}
}
}
The real problem is :
when everything is alright with "messages" node, why is the "intents" node not being updated?
Given that I have made the IntentMessage class in the same way as FriendlyMessage class
I got my problem as commented by Wilik, I didn't mention the rules for "Intents" section in the "rules" section of the database. Now I'm getting proper data.