仅当通过python firebase SDK添加文档时,在angularfire上更新空文档

时间:2019-09-19 08:09:55

标签: python google-cloud-firestore

我绝对不是Firestore和angular的新手,但是经过几天的工作,我设法编写了一个使用google firestore作为后端的离子/角度网络应用程序。

每次在Firestore中添加/删除/更新条目时,该应用程序仅显示实时更新。

我通过订阅valueChanges对数据库中的更改做出反应:

  itemSubscription;

  private itemsCollection: AngularFirestoreCollection<Item>;
  items: Observable<Item[]>;

  constructor(private afs: AngularFirestore) {

    this.itemsCollection = afs.collection<Item>('zones/Zone1/trashdumps');
    this.items = this.itemsCollection.valueChanges();

    // subscribe() is used to get a stream of updates.
    this.itemSubscription = this.items.subscribe(
      //function invoked on every new collection snapshot
      (docs) => {
        docs.forEach( doc => {
          console.log('Current data:', doc);
        })
      },
      //function invoked on error
      (msg) => { console.log('Error Getting Location: ', msg); }
    );

我的数据库的典型条目是这样的

{
    "bags": 
    {
        "integerValue": "2"
    },
    "location": 
    {
      "geoPointValue": 
      {
        "latitude": 52.3696,
        "longitude": 4.86561111
      }
    }
  }

当我通过Google Firestore Web控制台手动将条目添加到firestore时,我的应用会收到正确的更新。

当我通过Rest API向Firestore添加条目时,我的应用会收到正确的更新。

当我使用python的firestore-admin模块将条目添加到firestore时,我的应用收到空更新。注意:只有条目创建时收到的实时更新为空!如果我只是重新加载我的应用程序并再次查询数据库,我将获得正确的输入!从各个角度来看,python编写的数据库条目都是正确的。

这是我的意思是“正确更新”(取自chrome控制台):

tab2.page.ts:50 Current data: Object
                              bags: 2
                              location: GeoPoint {_lat: 52.3696, _long: 4.86561111}
                              __proto__: Object

这是错误的“空”更新:

tab2.page.ts:50 Current data: Object
                              __proto__: Object

我已经尝试订阅snapshotChanges()而不是valueChanges()。元数据确实存在,但是没有.data()方法来获取字段。也要清空。

这是我如何在Python(简化)中将条目添加到firestore中的方法:


class MyPoint(object):
    def __init__(self, bags, lat, long):
        self.bags = bags
        self.location = GeoPoint(lat, long)

    @staticmethod
    def from_dict(source):
        # ...
        pass

    def to_dict(self):
        # ...
        return {
            'bags': self.bags,
            'location': self.location
        }

class MyDatabase(object):

    _firebaseConfig = {
        [...]
    }

    def __init__(self):
        # Use the application default credentials
        cred = credentials.ApplicationDefault()
        firebase_admin.initialize_app(cred, self._firebaseConfig)
        self.db = firestore.client()

    def send(self, point): 
        self.db.collection(u'mycollection').add(point.to_dict())

point = MyPoint(1,0.0,0.0)
db = MyDatabase()
db.send(point)

我做错什么了吗? firestore-admin是否可以分两个步骤执行条目创建,首先创建一个空记录,然后为其设置值?那会解释吗?

我希望这很清楚,谢谢您的帮助,真的是一个新手。

更新

我已经更准确地记录了当我订阅DocumentChangeAction Observables时会发生什么,并且我更加困惑。

在以下日志中,“ Doc”代表DocumentChangeAction,而“ data”代表实际的.payload.doc.data()文档正文。

从一个空的数据库开始,这是我添加第一点时收到的更新:

tab2.page.ts:49 Current Doc: {type: "added", payload: {…}}
tab2.page.ts:50 Current data: {}
tab2.page.ts:49 Current Doc: {type: "modified", payload: {…}}
tab2.page.ts:50 Current data: {bags: 1, location: GeoPoint}

确实是一个空的“添加”和随后的“修改”。我可以解决这个问题。

但这就是我添加第二点(“ bags = 8”一个)时得到的:

tab2.page.ts:49 Current Doc: {type: "modified", payload: {…}}
tab2.page.ts:50 Current data: {bags: 1, location: GeoPoint}
tab2.page.ts:49 Current Doc: {type: "added", payload: {…}}
tab2.page.ts:50 Current data: {}
tab2.page.ts:49 Current Doc: {type: "modified", payload: {…}}
tab2.page.ts:50 Current data: {bags: 1, location: GeoPoint}
tab2.page.ts:49 Current Doc: {type: "modified", payload: {…}}
tab2.page.ts:50 Current data: {bags: 8, location: GeoPoint}

太多了:4个更新。

  1. 上一个条目由于某些原因被修改。元数据可能不是字段
  2. 执行空添加
  3. 上一个条目会再次发送(?)
  4. 最后,发送带有数据的新条目更新

是我还是这真的不必要地复杂?

1 个答案:

答案 0 :(得分:0)

我进行了相同的测试,结果发现valueChanges将针对每次更改返回所有对象的列表。您应该寻找一种类似stateChanged的替代方案,它只会为您提供最新的更改。

    this.items = db.collection('mytesting').valueChanges();

    this.items.subscribe(
      //function invoked on every new collection snapshot
      (docs) => {
        docs.forEach( doc => {
          console.log('Current data:', doc);
        })
      },
      //function invoked on error
      (msg) => { console.log('Error Getting Location: ', msg); }
    );

在控制台登录时打印所有项目:

app.component.ts:21 Current data: {name: "nagaraj"}
app.component.ts:21 Current data: {name: "Sample"}
app.component.ts:21 Current data: {name: "Test"}
app.component.ts:21 Current data: {name: "Fetch"}

我添加了一个新项目{name: "Another"},它会打印

app.component.ts:21 Current data: {name: "nagaraj"}
app.component.ts:21 Current data: {name: "Sample"}
app.component.ts:21 Current data: {name: "Test"}
app.component.ts:21 Current data: {name: "Fetch"}
app.component.ts:21 Current data: {name: "Another"}

如果我将行更改为:

this.items = db.collection('mytesting').stateChanges();

它不会打印所有项目,只有状态更改为addedmodifiedremoved的文档。

但是,我使用了AngularFirestore,无需订阅valueChanges().subscribe(,我就可以在UI中显示相同内容:

app.component.ts

import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';  
  items: Observable<any[]>;

  constructor(db: AngularFirestore) {
    this.items = db.collection('mytesting').valueChanges();
  }
}

app.component.html

<ul>
  <li class="text" *ngFor="let item of items | async">
    {{item.name}}
  </li>
</ul>

我没有使用subscribe