How can I get access to every meteor user object? I tried this, but it shows Meteor.users does not have function forEach.
Meteor.users.forEach((user) => {
console.log("userId", user._id);
});
Then I tried this, but it says userId is undefined.
_.toArray(Meteor.users).forEach((user) => {
console.log("userId", user._id);
});
So how can I get it? Thanks
Meteor.users is a Mongo collection. Mongo collections provide the map method to iterate through all found elements, but first, you have to find them. If you want to map through all the users without exception, just map without arguments, like this:
Meteor.users.find().map(user => console.log(user));
There, user will be an object that represents a user, i.e. similar to what you retrieve with Meteor.user().
Another way to iterate through all users would be to first fetch them in an instance of Array and then apply lodash or underscore to it:
const users = Meteor.users.find().fetch();
_.map(users, user => console.log(user));
Related
I have been trying to get arrays working in Firebase, and I am aware that there are a lot of references and discussions about this online, and I have read through all of these and none of it works.
First off, the Firebase side. The structure containing the array and two example strings inside it:
Firebase Structure
collection -> document -> fields
userData profileImages URLs (array)
: https://firebasestorage.googleapis.com/v0/b/app-138804.appspot.com/o/jRwscYWLs1DySLMz7jn5Yo2%2Fprofile%2Fimage_picker4459623138678.jpg?alt=media&token=ec1043b-0120-be3c-8e142417
: https://firebasestorage.googleapis.com/v0/b/app-138804.appspot.com/o/jRwscYWLs3872yhdjn5Yo2%2Fprofile%2Fimage_picker445929873mfd38678.jpg?alt=media&token=ec3213b-0120-be9c-8e112632
The first issue I am facing is writing to this array in the database:
Firestore.instance.collection('userData').document('profileImages').updateData({
'URLs': _uploadedFileURL,
});
Whenever I add data to this array, it just overwrites the existing data. I need to be able to keep all the existing data intact and simply add the current new line to the array.
Once this is working, I then need to be able to return all of the strings in this array without needing to know how many of them there will be.
For this part, I basically have nothing at this point. I could show some of the things I have tried based on suggestions from other articles on this, but none of it is even close to working correctly.
im assuming that _uploadedFileURL is a String, and you are updating the property URLs, that's why your data gets overwritten, because you are changing the URLs value to a single string which is _uploadedFileURL. to solve this issue, simply get the current data inside profileImages before commiting the update. like so
final DocumentSnapshot currentData = await Firestore.instance.collection('userData').document('profileImages').get();
Firestore.instance.collection('userData').document('profileImages').updateData({
'URLs': [
...currentData.data['URLs'],
_uploadedFileURL
],
});
and for the second part of your question, all you need is to query for the profileImages
Future<List<String>> _getProfileImages() {
final document = Firestore.instance.collection('userData').document('profileImages').get();
return document.data['profileImages]
}
the result of the get method will be a DocumentSnapshot, and inside the data property will access the profileImages which is a List<String>.
Ok guys and girls I have worked this out. Part 1: appending data to an array in Firebase.
Firestore.instance.collection('userData').document('profileImages').updateDataupdateData({
'URLs':FieldValue.arrayUnion([_uploadedFileURL]),
});
Where _uploadedFileURL is basically a string, for these purposes. Now I have read that arrayUnion, which is super groovy, is only available in Cloud Firestore, and not the Realtime Database. I use Cloud Firestore so it works for me but if you are having issues this might be why.
Now what is extra groovy about Cloud Firestore is that you can similarly remove an element from the array using:
Firestore.instance.collection('userData').document('profileImages').updateDataupdateData({
'URLs':FieldValue.arrayRemove([_uploadedFileURL]),
});
So how to get this data back out again. A simple way I have found to get that data and chuck it into a local array is like so:
List imageURLlist = [];
DocumentReference document = Firestore.instance.collection('userData').document('profileImages');
DocumentSnapshot snapshot = await document.get();
setState(() {
imageURLlist = snapshot.data['URLs'];
});
From here at least you have the data, can add to it, can remove from it and this can be a platform for you to figure out what you want to do with it.
I'm using Firebase's Firestore to store and publish new events.
In the code below, I'm subscribing to a collection and want to be notified when a new items is added (this code is executing on a browser).
When I first connect, I would like to receive a true snapshot. However, once I'm connected to Firestore and have received an initial snapshot, with each new item, I only want to get the udpates, not the whole collection over and over again!
function queryExercise(exercise){
db.collection("exercises").where("exercise","==",exercise).onSnapshot(function(querySnapshot){
querySnapshot.forEach(function(doc){
var d_ = doc.data()
console.log(d_);
...do somethign with d_...
})
})
}
When I publish a new item to the collection, my console is full of all events received earlier...in other words, it is sending me the full snapshot, instead of just the deltas.
Am I doing something wrong or does the API really not support delta updates?
Looks like I needed to read on docChanges:
function queryExercise(exercise){
db.collection("exercises").where("exercise","==",exercise).onSnapshot(function(querySnapshot){
// \/-----this thing
querySnapshot.docChanges().forEach(function(change){
var d_ = change.doc.data()
console.log("Change type:", change.type, d_);
...
});
})
}
From https://firebase.google.com/docs/firestore/query-data/listen
That's the way Firestore queries work. If you don't provide a filter for which documents you want in a collection, you will get all the documents in that collection. The only way to change this behavior is to provide a filter in your query using a where clause.
It sounds like you have a thought in mind about what makes for a "new" document in your collection. You will need to represent that using some field in the documents in your collection. Usually this will be a timestamp type field that's added or modified whenever a document is created or changed. This will be part of your where clause that determines what's "new". Use this field as a filter to find out what's new.
I have a firebase realtime database trigger on a create node. my need is to update a property based on some condition in the create trigger for the same object. The way i am doing currently is below:
exports.on_order_received_validate_doodle_cash_order = functions.database.ref("/orders/{id}")
.onCreate((change, context) => {
console.log("start of on_order_received_deduct_doodle_cash")
const orderId = context.params.id
const order = change.val();
var db = admin.database();
const orderRef = db.ref('orders/')
return orderRef.child(orderId).update({"_verifiedOrder": true})
})
As you can see i am getting order id from context and then querying object again and updating it. My question is do i need to do this circus or can i just update it without querying again?
Generally it looks good. Just some small feedback to make you feel more confident about being on the right track.
Call the parameter snapshot instead of change because the parameter name change only make sense for the onUpdate event trigger.
You do not need to log that you're entering the function. Because entering and leaving the function is automatically logged by Firebase also.
You can remove the order variable that is unused.
You are actually not "querying" the object again. Making a reference to a node in the database doesn't make any network call itself. Not until you subscribe to receiving data. So doing orderRef.child(orderId) is not a query, it's just a database reference.
You can use the snapshot's own reference attribute to shorten your code a bit... effectively throwing away almost all code :-)
So your code code look like this instead. It is doing the exact same thing, just shorter. It was also correct from the beginning.
exports.on_order_received_validate_doodle_cash_order = functions
.database
.ref("/orders/{id}")
.onCreate((snapshot) => {
return snapshot.ref.child("_verifiedOrder").set(true);
});
But as mentioned in my comment above, you are effectively just setting a flag that is confirming that data was saved (or rather: confirming that the function was triggered). You might want to add some logic in there to check whether the order can be placed or not and then set the verified flag to true or false depending on that. Because with the logic of the implementation, all orders will have the value _verifiedOrder set to true, which is a waste of storage in your database.
I have a restaurant bookmarks list in my firebase, but I don't know how to delete a specific restaurant in my database.
So I have the function unfavorite(favorite) where I pass the favorite restaurant as a parameter. Till here, than I want to pass this parameters id to the query to remove from the database like this:
this.afDb.list(`bookmarks/${user.uid}/restaurant/${favorite.restaurant.id})`).remove();
here is a screenshot of my database list:
How can I remove that specific restaurant out of the bookmarks list?
You will first need to add an ".indexOn": ["id"] rule to your database something like this:
"bookmarks": {
"$user_id": {
// normal reads and write rules here
},
".indexOn": ["id"]
This step is necessary for firebase database because otherwise you wont be able to use the orderByChild() and equalTo() methods.
Then, where you have your delete function, you want to instead use:
exampleRef = yourDb.ref("bookmarks/${user.uid}"); //this is just to simplify your reference a bit
exampleRef.orderByChild('id').equalTo(theDeleteIDhere).once('value').then(snapshot => {
snapshot.forEach((restaurant) => {
restaurant.ref.remove();
});
}); //this is a Promise that you can modify to return "true" if successful for example
The example I provided is just the way I have done it before (i.e. I prefer to use promises; hence the then() becuase this makes it easier to return that promise in an angular service which allows me to check whether the request was successful). You can use any variation of this so long as you have the "indexOn" rule and you use any sort of "sorting" method firebase provides here
Method 2
When I wrote this I totally glanced over the ability to map your restaurants like such:
Lets say your project is already listing those restaurants. You can therefore save each restaurant's auto generated id to a variable or map:
restaurants; // this is a map like this <your-identifier:autoID>
you can then easily just call:
exampleRef.child(restaurants[yourIdentifier]).remove();
Is there a clean built in way of directly referencing the data value of the node above the database trigger? I understand I can get a parent ref which I could then query for the value, but if there was a more concise way of doing this that would be great thanks.
For clarity, I want to use a child node within an object as a trigger, and when it occurs get the value of the parent object directly, to avoid the function being invoked when other changes are made to the parent object like so:
const parentObject = {
triggerValue: 'I want the function to be triggered only on writes to this path',
parentValue: 'But I also want this value',
}
Thanks
I've googled for this answer like six times and keep having to re-implement the solution.
Here's how to get the parent data, post, from a child attribute, post.body, that's changed:
exports.doStuff = functions.database
.ref("/posts/{postId}/body")
.onWrite(event => {
return event.data.ref.parent.once("value").then(snap => {
const post = snap.val();
// do stuff with post here
});
});
You can use event.data.ref and event.data.adminRef to navigate the database. They are Reference objects and work exactly like they would if you were building a web app with Firebase on the client side. So, if using the parent property to navigate up a level works fine for you, then just use that. There's no additional special syntax.