Getting user array data from firestore using flutter - arrays

Within my firestore db I have the directory users which has user data as documents. The document is having two fields, String 'displayName' and Array 'friends'. I am struggling to retrieve the friends array and get it into a list in flutter within a stream. Any help is appreciated.
My code as it currently stands is as follows:
Stream<List<Memo>> get memos {
var userdocs = Firestore.instance.collection('users').document(userid).document('friends');
// Complete request and do list conversions
// Do more work using results
}
I recognize that this question has been asked before but I am very new to flutter and asynchronous programming do not completely understand the answers

The flutter SDK returns a Stream object which will emmit the values over time (realtime database). In your example, you are assigning a Stream value & expecting a List. In asynchronous programming you have to subscribe to an event so that whenever a value emitted, we can perform our desired operation.
var userdocs
Firestore.instance
.collection("users")
.document(userid)
.get()
.then((DocumentSnapshot ds) {
userdocs = ds.data
})
Or use await if you are inside an async function
var userdocs = await Firestore.instance
.collection("users")
.document(userid)
.get()

Related

Firebase functions how to access all children collections by one call?

Using firebase-admin, I have several collections inside one collection. I need them all, so I need to to 4 different calls. The first one for the "users" collection, and the other 3 are the children of "users":
const profile = await admin
.firestore()
.collection("users")
.doc(context.auth.uid)
.get();
const internProps = await admin
.firestore()
.collection("users")
.doc(context.auth.uid)
.collection("internProps")
.get();
const externProps = await admin
.firestore()
.collection("users")
.doc(context.auth.uid)
.collection("externProps")
.get();
const geoPath = await admin
.firestore()
.collection("users")
.doc(context.auth.uid)
.collection("geoPath")
.get();
Making 4 calls to the DB sounds expensive.. Is it possible to somehow call only the "users" and extract the children collections from it? Or there is no other way than calling the other 3 methods :/
Is it possible to somehow call only the "users" and extract the
children collections from it?
It is not possible, with one query, to get documents from a parent collection and children collections of this parent collection.
The reason is that, from a technical perspective, a parent collection and the sub-collections of the documents in this parent collection are not at all related to each other.
Let's take an example: Imagine a doc1 document under the col1 collection
col1/doc1/
and another one subDoc1 under the subCol1 (sub-)collection
col1/doc1/subCol1/subDoc1
These two documents (and the two immediate parent collections, i.e. col1 and subCol1) just share a part of their path but nothing else.
So you'll need to issue four queries, one for each (sub-)collection.
What you ask for can't be done with firebase.
However, if your concern is number of calls that are being made, consider making using a map instead of a subcollection. This way you can get all data with a single request

Save value to Firestore on Stripe successful payment status

I want to write the user free-input form data to Firestore based on them successfully completing the Stripe checkout through the PaymentElement. I was first trying to do so based on the stripe.confirmPayment method response, which did not work well. Any ideas or practical examples on how can this be implemented? I have also tried using Stripe Webhooks, but I am unsure how to pass the user free-input form data there. Can this generally be handled from the front end, or should I create Firebase function?
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: window.location.href
}
});

DiscordJS - Fetch Multiple Users at Once

Instead if fetching every user by itself, I am trying to fetch an array of users at once.
This is the code I am trying to use:
var idsArr= ['682999909523259483','234269235071811584','503303866016727050'];
const membersArr = await interaction.guild.members.fetch({
idsArr,
});
console.log(membersArr);
Even though I only give it an array of 3 IDs, it logs every member of the server.
Any suggestion on how to fix that?
I just searched through official discord.js examples, and found this:
// Fetch by an array of users including their presences
guild.members.fetch({ user: ['66564597481480192', '191615925336670208'], withPresences: true })
.then(console.log)
.catch(console.error);
Maybe you should do this instead:
var idsArr= ['682999909523259483','234269235071811584','503303866016727050'];
const membersArr = await interaction.guild.members.fetch({
user: idsArr,
});
console.log(membersArr);
(Notice field name user instead of idsArr)

Firestore function to listen for updates

I am a beginner in React native and firestore, and using these to build a kind of social media app, and I have a weird problem(I think I structured the db the wrong way). I want to have a feed, with all posts, no following-based, no nothing. The first time I structured my posts in db like this: users(collection)->user(doc)->thisUserPosts(collection inside doc) - but I couldn't find a way to fetch through all the thisUserPosts from all user(doc) and display them properly.
So I re-structured the db like this:
2 main collection, posts and users. Completely different. In users collection, only docs of users and their data(name, age, etc). In the other, their posts(name, media, desc, AND userId - where userId == the person who created it. userId field from posts collection docs should exist in users collection).
This second approach works just fine. In feed, I only fetch posts. But the problem arrises when I try to open the post(need to have this feature). I need to be able to display on react-navigation header the name of the user, yet I only have details of the post and only userId, which is to no good use.
So I came up with a solution : add a userName field in the posts collection doc, next to userId and simply display that. Now here's the catch: I need to figure a way(in firestore I think) to listen to updates from users collection docs, in case a user updates his name/username(I don't want to showcase the old name). And I don't know if that's possible inside firestore or how. Or is it better to find a different db structure?
TLDR: Need a function in firestore to listen to updates from other collection OR restructuring the db.
If you are fetching posts of a single user then you can just set a listener for his document.
Make sure that document has no sensitive information that must not be shared with others and is limited to the owner only.
If you are fetching posts from multiple users then you can use in operator:
db.collection("users").where("userID", "in", ["user_id1", "user_id2"])
.onSnapshot((snapshot) => {
console.log(snapshot.docs.map(user => user.data()))
});
If I assume you will be updating the new name in all the user's posts then you can set the listener on the posts document itself but that won't be nice in case all 30 posts fetched are from same user. That'll end up costing 30 reads just to update the same name.
Edit:
A simple example of reading a user's posts and listening updates on the user name:
const userID = "my_user_id"
// fetching user's 30 posts
const postsRef = firebase.firebase().collection("posts").where("userID", "==", userID).limit(30)
const postsSnapshot = await postsRef.get()
const postsData = postsSnapshot.docs.map(post => post.data())
// Array of posts data objects
// listening to change in user's name
firebase.firestore().collection("users").doc("user_id")
.onSnapshot((doc) => {
console.log("data: ", doc.data());
const newUsername = doc.data().username
const updatedPostsData = postsData.map(post => {
return ({...post, username: newUsername})
})
});

Alexa check if a new session was started by accessing session.new

This is the data that is being send by alexa to my skills backend. In the backend code I would like to test if the session is new or not and based on this information I would like to produce a different output. I try to access the session.new, but I don't know how and I could now find anything about it online so far.
const { attributesManager } = handlerInput;
const requestAttributes = attributesManager.getRequestAttributes();
requestAttributes.session.new
//this leads to the error "cannot read property new of undefined"
const { attributesManager } = handlerInput;
const requestAttributes = attributesManager.getSessionAttributes();
sessionAttributes.session.new
//this leads to the same error
I finally found out that this is not possible using the AttributesManager because this only allows access to request, session and permanent attributes. But session.new is not part of those. If you want to check if the Alexa session is new you have to use the so called RequestEnvelopeUtils.
Using those you can access if the session is new or not by using the following statement.
(Alexa.isNewSession(handlerInput.requestEnvelope))

Resources