Vue-Firebase: Updating children & writing to child - firebase

I started working with Firebase and Vue also with VueFire and i dont understand how to update child nodes at Firebase.
I opened a firebase project and connected to it and i can push data to it.
Firebase
I made a vue component
import db from '../FireBase'
let team = db.ref('Teams');//Reference to Teams at firebase
let miss = db.ref().child('Teams'); //Attempt to get to the children of Teams
export default {
name: "App",
firebase: {
Teams_loc: db.ref('Teams'),
Mission: this.Teams_loc.child('Teams'),
missionKey: db.ref().child('Teams').push("").key,
},
...
I manage to get the Teams from firebase and send data to it:
this.$firebaseRefs.Teams_loc.push({
"test": "tester"
});
Which works but when i try to update the children inside
this.miss.push({
"where": "am i"
})
I get the following error
Cannot read property 'child' of undefined
And when i try to update a child
this.$firebaseRefs.missionKey.update(arr[0]);//arr[0] is an object
I tried looking at quite a few places but nothing seems to do the trick.
Thanks,

When you do the following you are doing an error at the second line.
Teams_loc: db.ref('Teams'),
Mission: this.Teams_loc.child('Teams'),
There is no child of the Teams node that has a key with the value `Teams.
So if you want to update an item, you first have to get its key (e.g. -LEzOBT-mp.....) and do as follows, as explained in the doc:
updateItem: function (item) {
// create a copy of the item
const copy = {...item}
// remove the .key attribute
delete copy['.key']
//possibly update (or add) some values of (to) the item
this.$firebaseRefs.Teams_loc.child(item['.key']).set(copy)
}
Also (if I am not mistaking) doing db.ref() will generate an error because you have to pass a value to ref().
I suggest that you study a bit more the doc and the example: https://github.com/vuejs/vuefire and https://github.com/vuejs/vuefire/blob/master/examples/todo-app/index.html
Update following your comment. Details on how to "know the random generated key"
According to the documentation:
Each record in the bound array will contain a .key property which
specifies the key where the record is stored. So if you have data at
/Teams/-LEzOBT-mp...../, the record for that data will have a .key of
"-LEzOBT-mp.....".
Look at this part of the doc: https://github.com/vuejs/vuefire#array-bindings.
So with this you will get all the keys of the Teams object. You have now to choose the item you want to update.
You could also declare a query in your firebase object, like:
firebase: {
team21483: this.database
.ref('Teams')
.orderByChild('teamCode')
.equalTo('21483')
}
and you would get an array with only one team, the one with TeamCode = 21483.
The best approach, in this latest case, is to manually bind to this Firebase query with the $bindAsArray (or possibly the $bindAsObject) instance methods, using a variable that you pass to equalTo().

Related

Determine RTDB url in a trigger function

i m bulding a scalable chat app with RTDB and firestore
here is my raw structure of shards
SHARD1
Chats {
chat01: {
Info: {
// some info about this chatroom
},
Messages ...
}, ....
}
SHARD2...
now i have write triggers on all the info nodes of all the shards.
i want get the ID of the shard
How do i know what shard it actually ran on ?
[EDIT]
console.log(admin.app().name); // it prints "[DEFAULT]" in console
Puf and team please help
When a Realtime Database trigger is invoked, the second argument is an EventContext object that contains information about the database and node that was updated. That object contains a resource string, which has what you're looking for. According to the documentation for that string, it's name property will be formatted as:
projects/_/instances/<databaseInstance>/refs/<databasePath>
The databaseInstance string is what you're looking for. So, you can just split the string on "/" and take the 4th element of that array:
export const yourFunction = functions.database
.instance('yourShard')
.ref('yourNode')
.onCreate((snap, context) => {
const parts = context.resource.name.split('/')
const shard = parts[3]
console.log(shard)
})
If all you need is a reference to the location of the change, in order to perform some changes there, you can just use the ref property on the DataSnapshot that was delivered in the first argument, and build a path relative to there.

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 access an object into another object in a query database from firebase functions?

I am trying to access to a object into another object in my firebase database, i have a structure like this:
I want to get all the objects that have the email that i send by parameters, i am using .child to access to the childs into my object but i am not success with the query, this is my code
$ ref_db.child("/groups").child("members").orderByChild("email").equalTo(email).once("value", (snapshot)=>{
console.log(snapshot.val());
});
The snapshot.val() always is undefined.
could you help me with the query?
One efficient way to get "all the groups that have that email inside the members object" would be to denormalize you data and have another "main node" in your database where you store all "members" (i.e. their email) and the "groups" they belong to.
This means that each time you add a "member" node under a "group" (including its email) you will also add the group as a child of the member email, in this other "main node".
More concretely, here is how would be the database structure:
Your current structure:
- groups
- -LB9o....
...
- members
- -LB9qbd....
-email: xxxx#zzz.com
- -LBA7R....
-email: yyyyy#aaaa.com
And the extra structure:
- groupsByMembers
- xxxxxx#zzzcom
- Grupo1: true
- yyyyy#aaaacom
- Grupo1: true
- Grupo2: true
- bbbcccc#dddcom
- Grupo6: true
- Grupo8: true
Note that in the "extra structure" the dots within an email address are removed, since you cannot include a point in a node id. You will have to remove them accordingly when writing and querying.
This way you can easily query for the list of groups a member is belonging to, as shown below. Without the need to loop several times over several items. This dernomalization technique is quite classic in NoSQL databases.
const mailToSearchFor = xxxx.xx#zzz.com;
const ref = database.ref('/groupsByMembers/' + mailToSearchFor.replace(/\./g, ''));
ref.once('value', snapshot => {
const val = snapshot.val();
for (let key in val) {
if (val.hasOwnProperty(key)) {
console.log(key);
}
}
});
In order to write to the two database nodes simultaneously, use the update method as explained here https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields
This is because you have a random key before members, you need to go through the path and not skip a node, to be able to access the values:
ref_db.child("groups").child("-LB9oWcnE0wXx8PbH4D").child("members").orderByChild("email").equalTo(email).once("value", (snapshot)=>{
console.log(snapshot.val());
});

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()

Can we use Firebase update function for updating priority as well

I am updating some properties of my object in firebase using the update method. As part of the update call, can i also update the priority of my object?
I have a collection of objects stored in firebase. I am using the Javascript sdk to interact with my data. Whenever i update any property of an object, i set the priority of the object to Firebase.ServerValue.TIMESTAMP constant.
Now, i want to start storing the priority of each object in a property called UpdatedOnTimestampTs defined on the object. Whenever i update any property i will also update UpdatedOnTimestampTs with TIMESTAMP constant.
Now the problem is, I am unable to find a way to call the update function along with priority (no updateWithPriority like setWithPriority). So if I update the UpdatedOnTimestampTs and priority in two different operations using the TIMESTAMP constant i may (or will) end up with a different values.
How can i address this?
I know I'm way late on an answer here, but I'm just coming across the need for something similar now and updateWithPriority doesn't exist (nor a way to easily view/edit priorities in the Forge).
You can include the specially-named key, .priority in your update and it ought to achieve the desired effect.
The .priority key is documented in the Firebase REST API, but can be used in the other libraries.
So, in Javascript, the following would work if you only wanted to update the priority (which, there is setPriority for that):
var fb = new Firebase("http://a_firebase.firebaseio.com");
var ref = fb.child("/path/to/child");
var data = { ".priority": (new Date()).getTime() } //timestamp, as you mentioned
ref.update(data);
If you wanted to change the priority while you're updating other properties, which is what you had asked, just include it with the data you want to update:
var fb = new Firebase("http://a_firebase.firebaseio.com");
var ref = fb.child("/path/to/child");
var data = {
"property1": "updated_val",
"property2": "updated_val2",
".priority": (new Date()).getTime(), //timestamp, as you mentioned
}
ref.update(data);
EDIT: To be clear, this will update the priority at the location of the child reference (i.e. /path/to/child) not the priorities of the individual children that are being updated (i.e. priorities of property1 and property2). If you wanted to include a priority for the children that are being updated, and the children are leaf nodes (i.e. string, number, boolean), then you can use the specially-named .value key in conjunction with the .priority key to do so.
The following example shows how to update the priority for the root location that the update is occurring from (i.e. path/to/child) as well as for both the children that are being update (i.e. property1 and property2). Obviously, you could selectively pick which priorities to update if you didn't want to update them all.
var fb = new Firebase("http://a_firebase.firebaseio.com");
var ref = fb.child("/path/to/child");
var newPriority = (new Date()).getTime(); //timestamp, as you mentioned
var data = {
"property1": {".value": "updated_val", ".priority": newPriority},
"property2": {".value": "updated_val2", ".priority": newPriority},
".priority": newPriority
}
ref.update(data);

Resources