How to push an object in array field using Firebase DB - reactjs

I want to push an object in array field of Firebase database.
I've tried,
const friendObj = {
first_name: item.first_name,
last_name: item.last_name,
username: item.username,
phoneNumber: item.phoneNumber,
email: item.email,
}
db.collection('users')
.doc('documentId')
.set({ friends: friendObj })
I want to add an object in friends array of below table.
My firebase table looks like below
Can anyone please help me, I'm having difficulty while add value in DB.

Firebase doesn't actually have a data type as arrays, but you have few alternatives to store data as an array using an alternative (like sets) and there are methods specifically to work with those.
Check this link for an implementation
https://stackoverflow.com/a/40055996/11945277

Related

Shorten multiple lines of setState code in react

This question is just for the purpose of improving my codes in React which currently looks very dirty and unreadable. I have 10-15 forms field which updated once I get values from APIs.
Here is the code from which I did this,
this.setState({smtpServer:res.data.data[0].smtpServer});
this.setState({senderName:res.data.data[0].senderName});
this.setState({senderEmail:res.data.data[0].senderEmail});
this.setState({smtpPorts:res.data.data[0].smtpPort});
this.setState({username:res.data.data[0].username});
this.setState({password:res.data.data[0].password});
this.setState({authType:res.data.data[0].authType});
There is also lots more of setState method which I didn't add. This makes my component code complex. Is there any method to shorten these codes.
You can destructure the data and use a single setState with shorthand object assignment (i.e. keys are named the same as the variables)
const {
smtpServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType
} = res.data.data[0];
this.setState({
smtpServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType
});
Or, if res.data.data[0] has all the properties you want to store in state, more succinctly
this.setState({...res.data.data[0]});
You can shorten them by fitting it all into a single object state using setState. First try to destructure your res.data.data[0] object in order to handle the individual attributes better:
const { smptServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType} = res.data.data[0];
Next you can set state in one GIANT OBJECT with each attributes. ES6 allows javascript to use key only instead of key-value pairs when the key and value have the same name.
Thus: const objName = {username:username, password:password} can also be typed as
const objName = {username,password}
By that logic you can just setState as:
this.setState({ smptServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType});
Hope this helps.
Assuming these calls are happening in sequence, it could be written as
const data = res.data.data[0];
this.setState({
smtpServer: data.smtpServer,
senderName: data.senderName,
senderEmail: data.senderEmail,
smtpPorts: data.smtpPort,
username: data.username,
password: data.password,
authType: data.authType
});
Or if there's nothing else in that object, you could just simply do
this.setState(res.data.data[0]);
or
this.setState({ data: res.data.data[0] });
It can be achieved in a very simple way as below:
You can take that data in one variable and then you can assign it in the state.
const data = res.data.data[0];
this.setState({...data});
You can assign it directly without the use of an extra variable.
this.setState({...res.data.data[0]});

Meteor inserting into a collection schema with array elements

Hi I created a SimpleSchema for a Mongo collection which has a variable number of sub-documents called measurables. Unfortunately it's been a while since I've done this and I can't remember how to insert into this type of schema! Can someone help me out?
The schema is as follows:
const ExerciseTemplates = new Mongo.Collection('ExerciseTemplates');
const ExerciseTemplateSchema = new SimpleSchema({
name: {
type: String,
label: 'name',
},
description: {
type: String,
label: 'description',
},
createdAt: {
type: Date,
label: 'date',
},
measurables: {
type: Array,
minCount: 1,
},
'measurables.$': Object,
'measurables.$.name': String,
'measurables.$.unit': String,
});
ExerciseTemplates.attachSchema(ExerciseTemplateSchema);
The method is:
Meteor.methods({
addNewExerciseTemplate(name, description, measurables) {
ExerciseTemplates.insert({
name,
description,
createdAt: new Date(),
measurables,
});
},
});
The data sent by my form for measurables is an array of objects.
The SimpleSchema docs seem to be out of date. If I use the example they show with measurables: type: [Object] for an array of objects. I get an error that the the type can't be an array and I should set it to Array.
Any suggestions would be awesome!!
Many thanks in advance!
edit:
The measurable variable contains the following data:
[{name: weight, unit: kg}]
With the schema above I get no error at all, it is silent as if it was successful, but when I check the db via CLI I have no collections. Am I doing something really stupid? When I create a new meteor app, it creates a Mongo db for me I assume - I'm not forgetting to actually create a db or something dumb?
Turns out I was stupid. The schema I posted was correct and works exactly as intended. The problem was that I defined my schema and method in a file in my imports directory, outside both client and server directories. This methods file was imported into the file with the form that calls the method, and therefore available on the client, but not imported into the server.
I guess that the method was being called on the client as a stub so I saw the console.log firing, but the method was not being called on the server therefore not hitting the db.
Good lesson for me regarding the new recommended file structure. Always import server side code in server/main.js!!! :D
Thanks for your help, thought I was going to go mad!

Inserting encapsuled object in firestore and goods practices

I have a question about to insert object in firestore in angularfire:
My object Person.ts
name: String
age: Number
//--constructor--
//--getters and setters--
if I do this, insert ok: (BUT is this good practice?)
[person.component.ts]
this.db.collection("person").add({
name: this.person.$nome,
age: this.person.$email
})
...
but if I try:
[person.component.ts]
this.db.collection("person").add({
Person: this.person
//or this this.person
})
I get this error in browser console:
Function DocumentReference.set() called with invalid data. Unsupported field value: a custom Person object (found in field Person)
at new FirestoreError (error.js:149)
at
Firestore only accepts a JavaScript object embedded within a document if it is a “pure” object, this means you can't use custom objects while coding with TypeScript.
Change your code to:
this.db.collection("person").add(Object.assign({}, this.person));

How to set the key name on an array in Angularfire

I am creating arrays using Angularfire but I am unable to set the key name. Firebase is automatically giving me a cryptic key (eg Jm9vLy8Lye-KS35KsmL) but I would like to set it myself to something more meaningful. It is unclear how I do this in Angularfire. I am using the $add method on $firebaseArray:
var firebaseRef = new Firebase("https://firebase_location");
$scope.messages = $firebaseArray(firebaseRef);
$scope.messages.$add(
{
FirstName: patient.FirstName,
LastName: patient.LastName
}
).then(function(firebaseRef) {
var id = firebaseRef.key();
});
The data is stored fine and I can see it on my dashboard. However, id is always a cryptic firebase value. I would love to be able to set it myself to something meaningful. In my case the individual patient's ID would be meaningful...
Any thoughts?
Thank you!
Thanks for the response.
I found that the child function will do what I need. I first specify the child and then set it.
var patient_child = firebaseScreenRef.child(patient.PatientId);
patient_child.set(
{
FirstName: patient.FirstName,
LastName: patient.LastName,
});
Adding an item to a firebase array make firebase define a unique id for you. If this is not what you want, I think you can try getting the "messages" object with $firebaseObject, instead of getting just the list with $firebaseArray. Then you will be able to edit your object in js, in order to add your items to the messages collection. In this way you can use the id that best suits your needs. Finally, you have to $save() your entire object. Look here: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject
Hope this helps.
For your question, I found an explanation. You don't need to use firebaseObject, you should use ref directly:
var ref = new Firebase(FURL);
createProfile: function(id ,user) {
var profile = {`enter code here`
name: user.name,
email: user.email,
gravatar: get_gravatar(user.email, 40)
};
var profileRef = $firebaseArray(ref.child('profile').child(id));
return ref.child('profile').child(id).set(profile);
},
In the code, I use ref to reference my URL. With profileRef, I created a child profile and I added id for the profile. Afterwards, I use ref directly to set the value profile for the id that I want. You see, it is very easy.

Data Modeling Best Practices in Firebase/AngularFire

I'm developing an application in Firebase for the first time and was curious how I should model the data between two objects, a user and a post. I come from more of a relational db background and was curious not only how this would be done in nonrelational DBs but specifically how to set up a relationship between two objects in Firebase.
For example, my application has many Users, and each user creates many Posts.
User {
firstName: String,
lastname: String,
userName: String
}
Post {
title: String,
content: String,
date: Date,
writtenBy: [User object?]
}
How should I structure these two objects in Firebase so that a Post belongs to a User, but all Posts can be queried for regardless of User, and both User and Post objects can be edited without disrupting the other object's data and/or relationship?
And how should I create new "relational" objects via firebase:
sync.$set({userA: {
firstname: "Billy",
lastName: "Bob",
userName: "BillyBob",
Posts: {
// .....
}
}
});
Thanks!
Firebase is built with performance in mind. This is the reason you have to design data structures differently, normalization is your enemy in most cases. Every object in Firebase can be accessed by URL, and you should always keep this in mind.
There are still many ways of designing the data structures, it depends on what queries do you want to execute. If one of the queries is to be able to display all messages (I believe a number of latest messages would be the most common use case), but at the same time you want to be able to show messages per user than one of the possible data structures could look like this:
User {
userId(assigned by Firebase automatically) {
firstName: String,
lastname: String,
userName: String
}
}
Post {
User {
userId(matching userId in the User object) {
postId(assigned by Firebase for every new post automatically) {
title: String,
content: String,
date: Date,
writtenBy: String, userName or userId (this is not really needed, but may keep it for easier data access)
}
}
}
}
Then you can change any user data without triggering data change events in Posts, like in your example, (which would be extremely heavy if you have large number of messages).
You can get all messages independently of user:
var postListRef = new Firebase(URL);
var lastPostQuery = postListRef.child("Post").limit(500);
You can also use startAt() and endAt() quesries https://www.firebase.com/docs/web/api/query/limit.html
As a drawback - you have to unpack every message in the for loop if you need to show only messages, but I would expect you would show user info as well, so it should be ok.
If you want to listen for just one user messages, it's very simple and fast:
var postListRef = new Firebase(URL);
var lastPostQuery = postListRef.child("Post/User").child(userId);
And Angular/AngularFire has great support for this kind of data structures.
I am also new to Firebase, I would recommend the following structure.
Users: {
userID: {
firstName: String,
lastname: String,
userName: String,
posts: {
postID1:true,
postID2:true
}
Posts: {
postID1:{
title: String,
content: String,
date: Date,
writtenBy: userID
}
}
It allows you to get the latest posts without having to through any users. Plus you can get all the post made by any user.

Resources