【问题标题】:Firestore: Add Custom Object to dbFirestore:将自定义对象添加到数据库
【发布时间】:2018-03-16 15:56:23
【问题描述】:

早安,

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

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]:使用无效数据调用函数 DocumentReference.set()。数据必须是一个对象,但它是:一个自定义的 Sponsor 对象

我该如何解决这个问题?

【问题讨论】:

    标签: angular firebase angularfire2 google-cloud-firestore


    【解决方案1】:

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

    所以在你的情况下它会是

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

    【讨论】:

    • 这行得通,但我发现它非常“hack-ish”。为什么 Firebase 没有正确的处理方法?
    • 这很好用,但你应该注意Object.assign 不适用于深度克隆。
    • 不适合嵌套对象
    【解决方案2】:

    您还可以将对象序列化为 JSON 并将其反序列化回常规 JavaScript 对象,例如

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

    适用于深度嵌套。

    【讨论】:

    • 您在使用此方法时遇到过任何限制吗?我认为查询数据会很困难,还是我弄错了?
    • 这会在保存到 Firestore 时损坏时间戳对象。
    【解决方案3】:

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

    【讨论】:

    • 推荐哪种方法?
    • 我发现使用 '.set(classToPlain(yourObject))' 的组合效果很好
    • 从最近开始,firebase 有了一个名为withConverter 的函数。您可以通过classToPlainplainToClass 进入它。这样你编码的方式就很清楚了。 (仅此而已)firebase.google.com/docs/reference/node/…
    【解决方案4】:

    感谢 Fabian Wiles - 我明白了!

    虽然 firebase 可以将对象内的数据发送到数据库,但当数据返回时,它无法将其实例化回您的类的实例。因此不允许上课

    只需像这样保存一个对象:

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

    【讨论】:

    • 只要你只使用接口,而不是类构造函数,这就可以了。
    【解决方案5】:

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

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

    }

    const project = {} as Launch;

    this.db.collection('launches').add(project);

    【讨论】:

      【解决方案6】:

      firebase 的行为真的很奇怪。以及我如何修复它 - 通过创建新接口并将转换方法添加到我的类:

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

      【讨论】:

        【解决方案7】:

        如果你使用 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

        【讨论】:

          【解决方案8】:

          我在使用 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

          【讨论】:

            【解决方案9】:
            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());
            }
            

            【讨论】:

              【解决方案10】:

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

              只需使用扩展运算符将类实例“分解”成一个空对象,例如{...myClass}

              let myClass = new ClassInstance(
                "newClass",
                "This is a new class instance"
              );
              
              addDoc(dbReference, { ...myClass }).then(() => {
               console.log("Document successfully written!");
              });
              

              【讨论】:

                猜你喜欢
                • 2020-12-28
                • 1970-01-01
                • 1970-01-01
                • 2020-05-17
                • 2023-03-06
                • 2020-12-15
                • 2023-03-26
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多