Firestore:将自定义对象添加到数据库

Firestore: Add Custom Object to db

早上好,

我尝试从这个 class 添加一个新创建的对象:

export class Sponsor implements ISponsor {

  title: string;    
  description?: string;
  creation: ICreation;

  constructor(title: string, description: string, author: string) {
     this.title = title;
     this.description = description;
     this.creation = new Creation(author);
  }
}

在我的服务中,创建函数如下所示:

createSponsor(sponsor) {
   sponsor.id = this.afs.createId();
   return this.collection.doc(sponsor.id).set(sponsor);
}

当我以这种方式尝试时,出现以下错误:

FirebaseError: [code=invalid-argument]: Function DocumentReference.set() called with invalid data. Data must be an object, but it was: a custom Sponsor object

我该如何解决这个问题?

感谢 Fabian Wiles - 我明白了!

while firebase could send the data inside your object to the database, when the data comss back it cannot instantiate it back into an instance of your class. Therefore classes are disallowed

像这样保存一个对象:

interface Person{
  name: string;
  age: number
}

var person: Person = { name: 'Toxicable', age: 22} ;

您也可以使用 Object.assign({}, 赞助商)

所以你的情况是

this.collection.doc(sponsor.id).set(Object.assign({}, sponsor));

firebase 的行为确实很奇怪。这就是我修复它的方法 - 通过创建新接口并将转换方法添加到我的 class:

export class Happening {
 constructor(
  public date: EventDate,
  public participants: Array<string>,
  public title: string,
  public text: string,
  public uid?: string,
  public id?: string
 ){}

 public toDto = (): HappeningDto => {
  return {
    date: {
      year: this.date.year,
      month: this.date.month,
      day: this.date.day
    },
    participants: this.participants ? this.participants : [],
    title: this.title,
    text: this.text ? this.text : '',
    uid: this.uid,
    id: this.id ? this.id : null
  }
 }
}

export interface HappeningDto {
 date: {
  year: number,
  month: number,
  day: number
 },
 participants: Array<string>,
 title: string,
 text: string,
 uid?: string,
 id?: string
}

现在,我可以

add(event: Happening){
  event.uid = this.uid;
  this.$afs.collection<HappeningDto>('events').add(event.toDto())
    .then(
      (success) => console.log(success),
      (err) => console.warn(err)
    )
}

您还可以将对象序列化为 JSON,然后将其反序列化为常规 JavaScript 对象,如

this.collection.doc(sponsor.id).set(JSON.parse( JSON.stringify(sponsor)));

适用于深层嵌套。

对于我的解决方案,我有一个 Interface

export interface Launch {
 id: string;
 date: Date;
 value: number;

}

const 项目 = {} 作为启动;

this.db.collection('launches').add(项目);

如果你使用Angular和AngularFire2,你可以使用AngularFirestype。 此模块旨在替换 AngularFirestore 并允许使用自定义对象直接获取和设置数据到 Firestore。

为此,需要 3 个步骤:

1. 安装angular-firestype

`npm install angular-firestype --save`

2.用映射对象

初始化AngularFirestype模块
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFirestypeModule, ModelType } from 'angular-firestype';
import { environment } from '../environments/environment';

import { User } from './user.ts';
import { Address } from './address.ts';
import { Message } from './message.ts';

/**
 * Definition of the app model mapping.
 * For more information, see https://github.com/bricepepin/angular-firestype#mapping-object.
 */
const model: {[key: string]: ModelType<any>} = {
  users: {
    type: User,
    arguments: ['username', 'image'],
    structure: {
      adress: Address
    },
    subcollections: {
      messages: Message
    }
  }
};

@NgModule({
 imports: [
   AngularFireModule.initializeApp(environment.firebase),
   AngularFireAuthModule,
   AngularFirestypeModule.forRoot(model),   // Import module using forRoot() to add mapping information
 ],
 declarations: [ AppComponent ],
 bootstrap: [ AppComponent ]
})
export class AppModule {}

3。注入 AngularFirestype 服务

import { Component } from '@angular/core';
import { AngularFirestype, Collection, Document } from 'angular-firestype';

import { User } from './user.ts';

@Component({
 selector: 'app-root',
 templateUrl: 'app.component.html',
 styleUrls: ['app.component.css']
})
export class AppComponent {
   const users: Observable<User[]>;
   const user: User;

   constructor(db: AngularFirestype) {
       const usersCollection: Collection<User> = db.collection<User>('users');
       usersCollection.valueChanges().subscribe(users => this.users = users);

       const userDoc: Document<User> = usersCollection.doc('user1');
       userDoc.valueChanges().subscribe(user => this.user = user);
       userDoc.set(this.user);
   }
}

您基本上可以像使用 Angularfirestore 一样使用 AngularFirestype。
有关详细信息,请参阅此处的主页:https://github.com/bricepepin/angular-firestype.

Firestore 不支持。但是你可以使用 https://github.com/typestack/class-transformer 它对我们来说非常好。

我在使用 vue 和 nuxt 时遇到了类似的问题

firebase.firestore().collection('example')
   .doc()
   .set({
       'foo' : 'boo'
   })

错误:

Data must be an object, but it was: a custom Object object

This link helped me

export class Sponsor implements ISponsor {
  title: string;    
  description?: string;
  creation: ICreation;

  constructor(title: string, description: string, author: string) {
     this.title = title;
     this.description = description;
     this.creation = new Creation(author);
  }

 toJson(){
   return {
     title:this.title,
     description:this.description,
     creation:this.creation
   }
}

在服务中,创建函数将如下所示:

createSponsor(sponsor) {
   sponsor.id = this.afs.createId();
   return this.collection.doc(sponsor.id).set(sponsor.toJson());
}

不确定我是否遗漏了什么,但现在似乎有一个更简单的解决方案来解决这个问题。

只需使用扩展运算符将 class 实例“展开”为空对象,例如 {...myClass}

let myClass = new ClassInstance(
  "newClass",
  "This is a new class instance"
);

addDoc(dbReference, { ...myClass }).then(() => {
 console.log("Document successfully written!");
});