RubyMotion Firebase (motion-firebase) How to retrieve data? - firebase

Using the motion-firebase library for RubyMotion Firebase (https://github.com/colinta/motion-firebase) I can set data easy enough either by doing:
firebase.set({ full_name: ['first_name' => 'Fred', 'last_name' => 'Flintstone'] })
or
firebase['first_name'] = 'Fred'
But I'm having trouble figuring out how to retrieve data.
I've tried the different firebase.query methods listed in the reponse readme but I'm definitely missing something.
I'd hoped it would be as simple as:
firebase.query['first_name']
=> 'Fred'
Could someone please explain how I might go about querying Firebase with a key and returning the value.

colinta here! You'll need to attach an observer (https://github.com/colinta/motion-firebase#attaching-observers-to-read-data).
firebase_ref.once(:value) { |snapshot| snapshot.value }
See https://www.firebase.com/docs/ios-api/Classes/FDataSnapshot.html for info on the FDataSnapshot type.

Related

Getting Users Details back from Firebase Flutter

I am very new to flutter and firebase and am really struggling.
I have been trying for about 2 weeks to work this out but I can't for the life of me work out what I am doing wrong.
I am trying to retrieve the 'DisplayName' from a 'users' collection with UID Document and DisplayName.
When I use The MyUser in other widgets using the provider package the DisplayName displays null, the console displays ' not again' so it appears that it's just not working at this point.(code below)
I have researched and I can't seem to find any why this code works. I am a NOOB so it may be something simple and after 2 weeks I thought I would ask for help.
Thanks In advance anything I can learn would be great.
Stream<List<MyUser>> get user {
var user = FirebaseFirestore.instance.collection('users');
return user.snapshots().map((list) => list.docs
.map((doc) => MyUser(
displayName: doc['DisplayName'] ?? 'not again',
))
.toList());
}

onUpdate change diff or patch value?

I am using the onUpdate event handler in Firebase Cloud Functions for the Realtime Database. Works great and I get the before / after snapshot values from the change object, as depicted here :
Before change : { '-M0ONRMFJxvClvoFnHP_': true, '-MNxnG-xnFrYOoU_H0U7': false }
After change : { '-M0ONRMFJxvClvoFnHP_': true }
I am curious if there's an "easy" way to get the diff or patch equivalent for this update operation ? Do I have to dive through the Javascript rabbit-hole and dig up a library (any suggestions ?) or is there a built-in feature inside the change object ?
Note : there's a reference to a fieldMask but I am not really seeing any ways to set this up (doesn't seem documented).
Thanks !
Well, I didn't find anything too exciting, so I just wrote the following that fits my specific purpose :
let beforeKeys = Object.keys(change.before.val() || {});
let afterKeys = Object.keys(change.after.val() || {});
let deletions = [];
let insertions = [];
deletions = beforeKeys.filter(item => !afterKeys.includes(item));
insertions = afterKeys.filter(item => !beforeKeys.includes(item));
and then I mapped the elements of each array to an async call for removal and addition to specific references in my realtime DB.
There's probably a more efficient way to achieve this, but that should work for now.
Thanks for coming to my TED Talk. 🙄

Trying to filter down chat messages using Flutter and Firestore

I'm trying to create a Blocked Users list in my chat app using the latest versions of Flutter Beta channel (1.23.0-18.1.pre) and cloud_firestore 0.14.3.
Here's my data structure:
At first, I tried something like this (Hardcoded just to test), by filtering the messages I'm querying from Firestore. Firebase doesn't like this.
query: firestore.collection('messages')
.where('userId', whereNotIn: ['123456789', '987654321'] )
.where('hashtag', isEqualTo: hashTag)
.orderBy('submittedAt', descending: true),
reverse: true,
I get this error:
E/FLTFirestoreMsgCodec(24331): java.lang.IllegalArgumentException: Invalid query. You have an inequality where filter (whereLessThan(), whereGreaterThan(), etc.) on field 'userId' and so you must also have 'userId' as your first orderBy() field, but your first orderBy() is currently on field 'submittedAt' instead.
After doing some more reading, filtering on the client-side by just hiding the messages actually better suits my needs.
Unfortunately, I'm running in circles. I'm currently thinking I would map a stream to a list, and then do something like this:
if (message.userId is in the list) {
isBlocked = true;
} else {
isBlocked = false;
}
And then filtering out the messages if isBlocked is true. I tried hardcoding the values for that and it worked. BTW, Sorry for the pseudocode, but I deviated so many times that now I'm simply lost.
I was wondering if this was the correct approach? Any suggestions would be rad. I also tried using a future list from a stream but I couldn't get that to work either.
Future<Stream<List<BlockedUser>>> getBlockedIds() async {
Stream<List<BlockedUser>> list;
Stream<QuerySnapshot> snapshot = FirebaseFirestore.instance.collection('user').doc('id').collection('blocked').snapshots();
list = snapshot.map((query) => query.docs.map(
(doc) => BlockedUser(
id: doc.data()['id'])
).toList());
return list;
}
I can't get that to work since I don't know what to do with that list.
Thanks, everyone!

Querying Firestore documents by Array or Map fields values in Firebase console

Here, I want to query by the value "ministoreid1" in Firebase console. But I am not able to figure out. Here, I am trying to do the query in console not using codes.
I have filed the feature request at Alex' suggestion. And the reply I received from Firebase Support:
Currently, there is no query similar to array-contains available in the Firestore Console. I can file a feature request ticket on your behalf. However, I can't guarantee anything at the moment, so please watch out for any updates on our blog or release notes for now. For the map field, you can try to filter on the console using the format: 'mapFieldName.keyName' in the field text box
So we can query for map values by 'mapFieldName.keyName'. I didn't know this before.
Here, I am trying to do the query in console not using codes.
Unfortunately, there is currently no way you can filter your documents in the Firebase console according to a value that exist in an array. As you can see, there are only the following operators:
== is equal to
> is after
>= is after and includes
< is before
<= is before and includes
But an whereArrayContains option it is not present yet. I recommend you file a feature request for that. It might be also useful for other developers.
The query that you perform in the console does't return any results because you are checking if the mini_stores_assigned is equal to ministoreid1, which obviously is not since the mini_stores_assigned property is an array and not a String so you can compare them.
For future use, Firebase has added the feature request by Ssuburat. You can now can filter your documents in the Firebase console according to a value that exist in an array.
###FILTER BLOGS BY USER.
for example if you have two collections (one to many)
/users
/blogs
blog and user has these schemes:
blog: { name,date,user:{myusername:true}}
//notice that user is a map or object and document blog has id itself wich you can use in user document and viceversa.
user:{name,lastname,blogs:{idblog1:true,idblog2:true}} //blogs is a map or object
if you want to filter by map object you can do this:
import firebase from "firebase/compat/app";
import { getFirestore } from "firebase/firestore";
const appFirebase = firebase.initializeApp(firebaseConfig);
export const dbFirebase = getFirestore(appFirebase);
const myuser= "myusername"
const q = query(collection(dbFirebase, "blogs"), where(`user.${myuser}`, "==", true));
const blogsSnapshot = await getDocs(q);
blogsSnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
console.log({blogsSnapshot});

Ordering data does not actually order anything

I'm trying to get a dataset of messages out of my firebase database and want the messages sorted by added/timestamp. But for some reason no orderby I put in the code is actually used. I tried doing these 2 things.
_messagesRef = FirebaseDatabase.instance.reference().child('messages/'+key);
_membersSubscription = _messagesRef
.orderByChild('timestamp')
.onValue//On valuechange
.listen((Event event) => _messagesSubscriptionCallback(event));
_messagesRef = FirebaseDatabase.instance.reference().child('messages/'+key);
_membersSubscription = _messagesRef
.orderByKey()
.onValue//On valuechange
.listen((Event event) => _messagesSubscriptionCallback(event));
Both give me back the same dataset that is not ordered by timestamp or key in the callback. I've added the output underneath
{
-LA-Aw6crEAV53LxdujP:{
sender:1508,
message:test s9 2,
timestamp:1523642778089
},
-LA-Arby61T1UG5URMn6:{
sender:1508,
message:test s9,
timestamp:1523642759679
},
-LA-AyC7F8KAqceZBE3j:{
sender:1509,
message:test emu 1,
timestamp:1523642786632
},
-LA22WiUfL2tbh7-OjtM:{
sender:1508,
message:Blaj,
timestamp:1523690904480
},
-LA-B29RRXbdOPT1mG7m:{
sender:1508,
message:tesy3,
timestamp:1523642806940
}
}
This is how the data should be.
I hope someone can help me with this issue. I think I might misunderstand how ordering data works with Firebase
Kind regards,
Namanix
The result you show is a JSON object with other objects in there. JSON objects are never ordered as far as I know, only retrievable by key. JSON Arrays would be, but it doesn't look like you get that. When you would change this to an array the document IDs would have to be inside the document instead of being the object key. My guess would be that 'orderBy' is meant to be used for example to limit the number of items you get for pagination. Than you can order by timestamp, limit the number of items to 20 and search from the last timestamp you got.
I think if you want to order them I would put them in a new list of objects which can be ordered.
Most likely (it's hard to be sure without seeing _messagesSubscriptionCallback) you're throwing the ordering information away when you convert the data from Firebase into a plain JSON object, which (as Rene also says) doesn't have any defined order.
But the data your request from Firebase does have ordering information, you just have to be sure to not drop it.
The usual way to do this is to listen for onChildAdded instead of onValue. With that Firebase will invoke onChildAdded for each child in turn, and it will do so in the order you requested.
Also see this example and for example what FirebaseAnimatedList does here.
I now temporarily fixed it by doing this in my callback. But this feels like a very bad way to fix it. I hope to get some thoughts on this.
static void _messagesSubscriptionCallback(Event event) {
_messagesList.clear();
_messages.clear();
_messages = event.snapshot.value;
_messagesList = _messages.keys.toList();
_messagesList.sort((a, b) {
return b.compareTo(a) ;
});
onMessagesChange();
}

Resources