我绝对不是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个更新。
是我还是这真的不必要地复杂?
答案 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();
它不会打印所有项目,只有状态更改为added
,modified
和removed
的文档。
但是,我使用了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
。