Getting reference to an item using AngularFire2 - firebase

I am using AF2 v5 and using the Real-time database.
I want to get the reference to a node or item in my data. After checking the docs I found the following.
const listRef = db.list('items');
Notice the user of the .list() method. The return type of the above statement is AngularFireList{[]}.
I was hoping to get the return type of Reference.
Is this the correct way to get a reference to a node so that I can perform CRUD to it?

You need to use db.object() to get a single firebase.database.Reference.
const item = db.object('items/itemID').valueChanges();
Check the official doc
You can perform the CRUD like
const itemRef = db.object('items/itemID');
itemRef.remove();
itemRef.set({ name: 'new name!'});
itemRef.update({ age: newAge });

Related

Firebase realtime database returns all children instead of the single indicated one by OrderByKey().EqualTo(xxx)

I keep public profiles from my users like this:
Using the Unity SDK, I try to fetch a subset of the profiles with this query:
var profileDbRef = GetSharedDBInstance().RootReference.Child("profiles");
Query q = profileDbRef.OrderByKey();
userIds.ForEach(uId => q.EqualTo(uId));
q.GetValueAsync().ContinueWithOnSuccess(snapshot => {
var profiles = (Dictionary<string, object>)snapshot.Value;
// here profiles dictionary contains ALL my users, not the ones included in userIds list.
}
I receive all my users in the resulting snapshot. Not sure what's happening here? Is there a bug in the Unity SDK?
Turns out q.EqualTo(uId) returns a new query object. So the fix was to change this one line to update the q variable.
userIds.ForEach(uId => q = q.EqualTo(uId));

How to query an array of objects in a Firebase Cloud Function, to get a matching object and then update

I am using a scheduled task in a Firebase Cloud Function to query an array which contains a number of objects that need to be updated if a matching condition exists. My current attempt is using the 'array-contains' method to get the objects, then loop over them to find a matching condition which will then batch update the items. This is my data structure:
I need to find an object that is <= the current time, and also if the 'active' value = false.
export const liveMeetingsTrigger = functions.runWith( { memory: '1GB' }).pubsub
.schedule('every 1 minutes').onRun(async context => {
const now = admin.firestore.Timestamp.now();
const liveMeetings = await admin.firestore().collection('fl_content').where('meeting', 'array-contains', 'liveMeetingDate').get();
const batch = admin.firestore().batch();
liveMeetings.forEach(doc => {
if(doc.data().liveMeetingDate <= now && doc.data().active == false){
batch.update(doc.ref,'active',true);
}
});
return await batch.commit();
});
I have also tried using an exact object in the query instead of just using 'liveMeetingDate', but still get no results back, any help would be great - thanks.
Debugging: As the array I am trying to reach is inside of the (map) object 'liveMeetings' i have tried the dot notation (liveMeetings.meeting) with no success. Also trying a new collection with the the 'meeting' array at top level has provided no success.
Simple logging in the console (liveMeetings.size) shows that nothing is being returned on the query, so therefore the logging does not even reach the loop in the code.
As explained in this anwser the following query will not work:
const liveMeetings = await admin.firestore().collection('fl_content').where('meeting', 'array-contains', 'liveMeetingDate').get();
because the meetings array contain some objects, instead of "simple" or primitive data (e.g. string, number...).
You could query it with the exact objects, like:
const obj = {active: false, liveMeetingDate: ..., meetingId: ..., ....};
const liveMeetings = await admin.firestore().collection('fl_content').where('meeting', 'array-contains', 'obj').get();
Another approach would be to create a new collection which contains the similar documents (same Document ID) but with a meeting Array that contains only the liveMeetingDate property.
Finally, note that since your Array is within a map, you need to do
await admin.firestore().collection('fl_content').where('liveMeetings.meeting', 'array-contains', ...).get();
(PS: I don't mark this question as duplicate since you expressly ask for more help in the comments of the duplicate question/answer)

Firebase cloud functions: is `createId()` available on the server side?

If I want to write to the database from my client side, I can inject an AngularFirestore instance and generate an id automatically using createId():
const individualId = this.angularFirestore.createId();
But if I want to do the same thing in a cloud function, using the Firestore admin API, I can't find an equivalent operation. I can create a Firestore instance in a cloud function by running
const db = admin.firestore();
However, the object that is created has no createId() function available.
Is there an equivalent to createId() that I can use within a cloud function?
I understand from this issue and this article that "AngularFirestore.createId() generates a new id from a symbolic collection named '_'".
If you want to mimic this behaviour in a Cloud Function, you could use the doc() method of a CollectionReference without specifying any path. You will get a DocumentReference, and then you can use the id property to get the "last path element of the referenced document".
Something like the following:
const db = admin.firestore();
const docRef = db.collection('_').doc();
const newId = docRef.id;
Note that, as explained in the issue referred to above, it is a bit weird to "use a generic collection instead of an actual collection" to generate an id, because you would normally use the collection in which you want to create a new Document. But this is not a problem, according to this comment from James Daniels (who is a Firebaser), since the Firestore auto-generated ID is "just a random string and doesn't take the path into consideration at all".
in JavaScript, for the new Firebase 9 (January 2022). In my case I am developing a comments section:
const commentsReference = await collection(database, 'yourCollection');
await addDoc(commentsReference, {
...comment,
id: doc(commentsReference).id,
date: firebase.firestore.Timestamp.fromDate(new Date())
});
Wrapping the collection reference (commentsReference) with the doc() provides an identifier (id)

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});

How to get the id/key of added firebase item directly in Ionic 2?

I'm trying to get the id/key of added item after adding processing
for example, this is my add function
add(){
let todayTime = moment().format('YYYY-MM-DD, HH:mm')
this.afd.list('/questions/').push({
uemail: this.userService.email,
title: this.variables.title,
text: this.variables.text,
type: this.variables.type
})
}
So how can I get the id directly (when item added successfully) ?
According to firebase doc
let key = this.afd.list('/questions/').push().key;
You get the key before pushing your data. It is useful when you need simultaneously add data in different locations using .update()

Resources