Angular add new doc in firestore without list - node.js

I am new in angular and firebase, I got a crud operation project which work like below
export class EmployeeService {
employeeList: AngularFireList<any>;
selectedEmployee: Employee = new Employee();
constructor(private firebase: AngularFireDatabase) { }
getData() {
this.employeeList = this.firebase.list('employees');
return this.employeeList;
}
insertEmployee(empoloyee: Employee) {
this.employeeList.push({
name: empoloyee.name,
position: empoloyee.position,
office: empoloyee.office,
salary: empoloyee.salary
});
}
updateEmployee(emp : Employee){
this.employeeList.update(emp.$key,{
name : emp.name,
position : emp.position,
office : emp.office,
salary : emp.salary
})
}
deleteEmployee(key : string){
this.employeeList.remove(key);
}
}
Here as per my understanding to add a new record it add items into list which has been fetched through getData.
Is there possible to add a new doc in collection without fetching list
Thanks

You are not fetching any data.
this.firebase.list('employees') is a list binding. Data is only fetched if you add valueChanges() and subscribe() to this observable created by valueChanges()

Related

Get soft deleted records using Nestjs and TypeOrmQueryService

I am trying to get soft deleted records (deletedAt column) when using query from TypeOrmQueryService but looks like there is no way to do that. I know that I can use withDeleted if I use find or findOne but I cannot switch to these methods or use a query builder since it would require a lot of changed in the front-end.
#QueryService(Patient)
export class PatientQueryService extends TypeOrmQueryService<Patient> {
constructor(#InjectRepository(Patient) repo: Repository<Patient>) {
super(repo);
}
async getOnePatient(currentUser: User, patientId: number) {
const result = await super.query({
paging: { limit: 1 },
filter: { id: { eq: 1 } },
});
}
}

How to create multilevel nested queries in nestjs/graphql using #ResolveField?

Hello. I can't figure out how to create multiple levels of nested queries with #ResolveFiled. I hope for your help. 🙏
What I'm doing and Context:
I have a product. The product has a supplier. A vendor-specific product contains product variants. Variants contain options.
I need to make a request in 4 levels:
Product
ProductHasProvider
Product Variants
Variant Options
I use the "Code First" approach, created an ObjectType for each entity. Next, I create a "Product" resolver.
Creating a second level "ProductHasProvider" with #ResolveField
When adding a ResolveField ("Providers") - it appears inside the main resolver "Product" and resolves the Providers ObjectType. Okay, it works, I can make requests at the 2nd level correctly.
#ResolveField('Providers', () => [ProductHasProvider])
async getProductProviders (#Parent() product: Product) {
const { id } = product;
return await this.productListService.ProductsProviders( { id });
}
I want to make third level where ProductHasProvider has Variants. I decorate ProductHasProvider as the parent.
#ResolveField(('variants'), type => [Variant])
async getVariants (#Parent() productHasProvider: ProductHasProvider) {
const { id } = productHasProvider;
return await this.productListService.getVariants({ id });
}
In this case, this ResolveField defines the ObjectType for [Variants], but for some reason at the first level. That is, in Apollo studio, the field is displayed in "Product". I can't query Variants for ProductHasProvider.
query Products {
getProducts {
Providers {
id
}
variants {
id
options {
id
}
}
}
}
Expected behavior:
I add a new #ResolveField(() => [Variants]) with "ProductHasProvider" parent (Which is already #ResorveField for Product). And I can do 3rd and 4th level queries.
query Products {
getProducts {
id
Providers {
id
variants {
id
options {
id
}
}
}
}
}
Please tell me what I'm doing wrong and how to achieve what I want. Thank you.🙏
#ResolveField is to be put in a Resolver, to specify how to return a specific field for a specific entity.
In your case, you have a Resolver for Products, in which you specify a #ResolveField for the field Providers.
I'm guessing that you are adding another #ResolveField in the same Resolver, and it will specify how to return another field of Products.
What you want is to create another Resolver, for Providers, in which you specify how to return the field variants.
Here is how it is working for me :
#Resolver('Product')
export class ProductsResolver {
#ResolveField('Providers', () => [ProductHasProvider])
async getProductProviders (#Parent() product: Product) {
const { id } = product;
return await this.productListService.ProductsProviders( { id });
}
}
#Resolver('Provider')
export class ProvidersResolver {
#ResolveField('variants', () => [Variant])
async getProductProviders (#Parent() provider: ProductHasProvider) {
const { id } = provider;
return await this.variantsService.getVariantForProvider( { id });
}
}

How to update an entity with relations using QueryBuilder in TypeORM

I have UserEntity and AddressEntity, they are related as OneToOne, that's one user may have only one address. UserEntity has fields firstName, secondName, address. AddressEntity has fields country and city.
If I wanted to update UserEntity without doing it to its relations I would do this:
await entityManager.getRepository(UserEntity)
.createQueryBuilder('users')
.update(UserEntity)
.set(updateUserObject)
.where('users.id = :userId', { userId })
.execute();
where updateUserObject is formed from a request body. That's to say, if I need to update firstName, the object would look like this: { firstName: 'Joe' }. Now what is unclear is how to use that builder if I have the following updateUserObject:
{
firstName: "Bob",
address: {
"city": "Ottawa"
}
}
The official documentation does not address such cases.
You can achieve this using preload and save methods.
Update your UserEntity similar to below:
#Entity('user')
export class UserEntity {
...
#OneToOne(
() => AddressEntity,
{
// Make sure that when you delete or update a user, it will affect the
// corresponding `AddressEntity`
cascade: true,
// Make sure when you use `preload`, `AddressEntity` of the user will also
// return (This means whenever you use any kind of `find` operations on
// `UserEntity`, it would load this entity as well)
eager: true
}
)
#JoinColumn()
address: AddressEntity;
}
Now using entityManager, you can update all the fields that you want using the following way:
const partialUserEntity = {
id: userId,
firstName: "Bob",
address: {
"city": "Ottawa"
}
};
const userRepository = await entityManager.getRepository(UserEntity);
// Here we load the current user entity value from the database and replace
// all the related values from `partialUserEntity`
const updatedUserEntity = userRepository.preload(partialUserEntity);
// Here we update (create if not exists) `updatedUserEntity` to the database
await userRepository.save(updatedUserEntity);
However, you need to make sure that your UserEntity has an AddressEntity associated always. Otherwise, you will have to generate an id for AddressEntity like below before you execute save method.
/*
* If `updatedUserEntity.address.id` is `undefined`
*/
// `generateIDForAddress` is a function which would return an `id`
const generatedIDForAddress = generateIDForAddress();
const partialUserEntity = {
id: userId,
firstName: "Bob",
address: {
"id": generatedIDForAddress,
"city": "Ottawa"
}
};
Please note that under the hood, typeorm will run UPDATE statements separately for UserEntity and AddressEntity. This is just an encapsulation of multiple join statements (when executing preload method) and update statements (when executing save method) such that the developer can easily implement this scenario.
Hope this helps you. Cheers 🍻!

How to define a manytomany relationship on the same table in objectionjs?

I have an article table, where an article can cite multiple articles. Each article can also have a single author.
Article model :
class Article extends DefaultModel {
static get tableName() {
return "articles";
}
static get relationMappings() {
return {
author: {
relation: DefaultModel.BelongsToOneRelation,
modelClass: "Author",
join: {
from: "articles.authorId",
to: "authors.id"
}
},
mentions: {
relation: DefaultModel.ManyToManyRelation,
modelClass: "Article",
join: {
from: "articles.id",
through: {
from: "mentions.citingArticle",
to: "mentions.citedArticle"
},
to: "articles.id"
}
}
};
}
}
Mention model :
class Mention extends DefaultModel {
static get tableName() {
return "mentions";
}
static get idColumn() {
return ["citingArticle", "citedArticle"];
}
}
What I'm trying to do, is insertGraph, the main article + the articles that are mentioned in it, here is what I have :
async function insertData(fullArticle) {
const articleTx = await transaction(Article.knex(), async tx => {
const references = fullArticle.references
.map(articleObj => {
return {
...articleObj.article,
author: articleObj.author
};
});
const article = await Article.query(tx).insertGraph({
...fullArticle.article,
author: fullArticle.author,
mentions: references[0]
});
return article;
});
console.log(articleTx);
}
I know this is only inserting the main row + the first row, but I ran into multiple problems :
The mention model has a composite key, when I try to insert using the code above I get a (node:5944) UnhandledPromiseRejectionWarning: error: column "citedArticle" of relation "mentions" does not exist.
I also got the same error when I try to add "#id" to the main article mentions relation, and "#ref" to the cited article, and insert them in 2 different objects.
A third problem I ran into here, was a unique constraint on both the citing and the cited article authors. What if both of them were written by the same author? I have a unique string column in the authors table that isn't the id, when I tried to insert I got duplicate key value violates unique constraint "author_isn". I'm not sure how I can update the row to reference the existing author id if that happens.

How to add a new field in Array of data in Firebase realtime database using Firebase Functions?

I am new to firebase. I have data in Firebase realtime database with following structure. My requirement is to add a new field to multiple (selected) records present under “user”.
Initial Data
db—>user
—pushId_1 (Auto Generated via push command)
name: user1
pushId_2
name: user2
Required final Data with one more field added (“newField”)
db—>user
—pushId_1
name: user1
newField: sample data
pushId_2
name: user2
newField: sample data
I have written following code to do this.
exports.sampleFunction = functions.database.ref('/db/user/{pushId}/')
.onCreate((snap, context) => {
console.log('onCreate called with snapshot id = ' + snap.key);
admin.database().ref('/db/user/').once('value').then(snapshot => {
if (snapshot.numChildren() > 1) {
var updates = {};
var count = 0;
snapshot.forEach((child) => {
if (!child.hasChild('newField') && count < 2) {
updates[child.key] = { newField: 'sample data' };
count++;
}
});
//return snapshot.ref.set(updates); //set is also giving same result.
return snapshot.ref.update(updates);
}
return null;
}).catch(error => {
console.error("error in fetching data from db." + error);
});
return null;
});
Problem is, this code is deleting existing field "name" and replacing it with “newField”.
Can you please help me in appending this new field to data without deleting existing fields.
Thanks
That's because you are using set instead of updating the node.
Set replaces any content while update adds fields if missing and only replace fields if they are present in new data.
return snapshot.ref.update(updates);
Also you are setting the data wrong to update. In key you need to have path relative to the ref you are calling the update instead of nested objects.
Instead of updates[child.key] = { newField: 'sample data' };, it should be
updates[`${child.key}/newField`] = 'sample data';
now when you call update with the child parent i.e. snapshot, it knows exactly which fields to update.
See the docs for more details: https://firebase.google.com/docs/database/admin/save-data#section-update

Resources