I have a MessageModel in which there are a few fields. But the field "edited" does not exist in the document of each message. It is a new field that I want to add later in the future. When I get all messages using stream it throws the error.
Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform
Is there any way I can check if the field "edited" exists in the model or ignore it?
This is my MessageModel:
factory MessageModel.fromJson(DocumentSnapshot snapshot) => MessageModel(
chatId: snapshot["chat_id"],
messageId: snapshot["message_id"],
userId: snapshot["user_id"],
you: snapshot["you"],
time: snapshot["time"],
seen: snapshot["seen"],
type: snapshot["type"],
message: snapshot["message"],
fileURL: snapshot["file_url"] ?? "" ,
thumbnail: snapshot["thumbnail"] ?? "" ,
isUploading: RxBool(false),
isPlaying: RxBool(false),
file: File("").obs,
thumb: Uint8List(5).obs,
edited: snapshot["edited"]
);
I am using this stream to get all my messages from firestore. Or can I check here if the field exists?
Flutter code:
Stream<List<MessageModel>> getMessages() {
Stream<QuerySnapshot> stream =
CollectionReferences.chatRef.doc(userID.value).collection("messages").orderBy("time", descending: true).snapshots();
return stream.map((data) => data.docs.map((e) => MessageModel.fromJson(e)).toList());
}
If you capture the data as a map, you can check if the map contains a key:
edited: (snapshot.data() as Map<String, dynamic>).containsKey("edited") ?
snapshot["edited"] : null
Related
My Flutter app uses Firbase Cloudfirestore as its backend. Later I'll want to add new features to my app which would require new fields in a Firestore document. How can I check whether the field exists in the document and return a default value if it doesn't?
Stream<List<Car>> streamCars() {
return _carsCollection.snapshots().map((snapshot) => snapshot.docs.map((document) => Car.fromDocumentSnapshot(document)).toList());
}
static Car fromDocumentSnapshot(DocumentSnapshot snapshot) {
return Car(
id: snapshot.id,
date: snapshot['date'] ?? Timestamp.now(),
seats: snapshot['seats'] ?? 0,
newFeature: snapshot['newFeature'] ?? '', // This field does not exist yet and throws error
);
}
This throws the error:
Bad state: field does not exist within the DocumentSnapshotPlatform
You can do it like so.
newFeature: (snapshot.data() as Map)['newFeature'] ?? ''
static Car fromDocumentSnapshot(DocumentSnapshot snapshot) {
return Car(
id: snapshot.id,
date: snapshot['date'] ?? Timestamp.now(),
seats: snapshot['seats'] ?? 0,
newFeature: snapshot['newFeature']==null ?'tjhjhjh': '', // check it if is null will solve the error
);
}
Firebase error (unhandled rejection)
React error on the browser:
Unhandled Rejection (FirebaseError): Function addDoc() called with invalid data. Unsupported field value: undefined (found in field username in document posts/MkHzQWzXyayty0KfQQgP)
Most probably the problem is in this code :
// complete function
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(url => {
// Post image on db
db.collection("posts").add({
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
caption: caption,
imageUrl: url,
username: username
});
setProgress(0);
setCaption("");
setImage(null);
});
}
);
}; ```
In the error, it says your variable username is undefined. You should make sure that it has a value. Meanwhile, you can do a quick and dirty fix like this:
db.collection("posts").add({
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
caption: caption,
imageUrl: url,
username: username || null,
});
This code will assign null to username when the variable username is undefined.
I'm trying to set up a collection of versioned documents in which I insert a new document with the same id and a timestamp whenever there's an edit operation. I use a unique compound index for this on the id and timestamp fields. CosmosDB is giving me MongoError: E11000 duplicate key error whenever I try to insert a document with a different id but an identical timestamp to another document. The MongoDB documentation says that I should be able to do this:
https://docs.mongodb.com/v3.4/core/index-unique/#unique-compound-index
You can also enforce a unique constraint on compound indexes. If you use the unique constraint on a compound index, then MongoDB will enforce uniqueness on the combination of the index key values.
I tried using a non-unique index but the Resource Manager template failed, saying that non-unique compound indexes are not supported. I'm using the node.js native driver v3.2.4. I also tried to use Azure Portal to insert documents but received the same error. This makes me believe it's not a problem between CosmosDB and the node.js driver.
Here's a small example to demonstrate the problem. I'm running it with Node v10.15.3.
const { MongoClient } = require('mongodb');
const mongoUrl = process.env.COSMOSDB_CONNECTION_STRING;
const collectionName = 'indextest';
const client = new MongoClient(mongoUrl, { useNewUrlParser: true });
let connection;
const testIndex = async () => {
const now = Date.now();
connection = await client.connect();
const db = connection.db('master');
await db.collection(collectionName).drop();
const collection = await db.createCollection(collectionName);
await collection.createIndex({ id: 1, ts: -1 }, { unique: true });
await collection.insertOne({ id: 1, ts: now, title: 'My first document' });
await collection.insertOne({ id: 2, ts: now, title: 'My other document' });
};
(async () => {
try {
await testIndex();
console.log('It works');
} catch (err) {
console.error(err);
} finally {
await connection.close();
}
})();
I would expect the two insert operations to work and for the program to exit with It works. What I get instead is an Error:
{ MongoError: E11000 duplicate key error collection: master.indextest Failed _id or unique key constraint
at Function.create (/home/node/node_modules/mongodb-core/lib/error.js:43:12)
at toError (/home/node/node_modules/mongodb/lib/utils.js:149:22)
at coll.s.topology.insert (/home/node/node_modules/mongodb/lib/operations/collection_ops.js:859:39)
at handler (/home/node/node_modules/mongodb-core/lib/topologies/replset.js:1155:22)
at /home/node/node_modules/mongodb-core/lib/connection/pool.js:397:18
at process._tickCallback (internal/process/next_tick.js:61:11)
driver: true,
name: 'MongoError',
index: 0,
code: 11000,
errmsg:
'E11000 duplicate key error collection: master.indextest Failed _id or unique key constraint',
[Symbol(mongoErrorContextSymbol)]: {} }
Is this expected behavior or a bug in CosmosDB's MongoDB API?
I need to iterate a node in a DatabaseReference in firebase. But it is wired that there is no forEach function in DataSnapshot that is in firebase_database library!
I also tried to use DataSnapshot object that is in firebase library (that has a forEach function in it) but I got a error:
[dart] The argument type '(DataSnapshot) → List<dynamic>' can't be assigned to the parameter type '(DataSnapshot) → FutureOr<dynamic>'.
And here is my code:
getAccountsList() {
return firebaseDbService.getAccounts().once().then((DataSnapshot snapshot) {
var list = [];
snapshot.forEach((DataSnapshot account) => list.add({
'id': snapshot.key,
'name': snapshot.child('name').val(),
}));
return list;
});
}
It's unclear what you are trying to do in your code, both child(String path) and val() do not exist in the class DataSnapshot, you can check here:
https://github.com/flutter/plugins/blob/master/packages/firebase_database/lib/src/event.dart#L27
Also you cannot loop like this:
for( var values in snapshot.value){
print("Connected to second database and read ${values}");
}
since you will get the following error:
which means also you cannot use forEach() on the snapshot to iterate.
Let's say you have this database, and you want to get the names:
user
randomId
name: John
randomId
name: Peter
You need to do the following:
_db=FirebaseDatabase.instance.reference().child("user");
_db.once().then((DataSnapshot snapshot){
Map<dynamic, dynamic> values=snapshot.value;
print(values.toString());
values.forEach((k,v) {
print(k);
print(v["name"]);
});
});
Here the reference points toward the node users, since snapshot.value is of type Map<dynamic,dynamic> then you are able to do this Map<dynamic, dynamic> values=snapshot.value;.
Then you loop inside the map using forEach() to be able to get the keys and values, you will get the following output:
This line I/flutter ( 2799): {-LItvfNi19tptjdCbHc3: {name: peter}, -LItvfNi19tptjdCbHc1: {name: john}} is the output of print(values.toString());
Both the following lines:
I/flutter ( 2799): -LItvfNi19tptjdCbHc3
I/flutter ( 2799): -LItvfNi19tptjdCbHc1
are the output of print(k);
The other two lines are the output of print(v["name"]);
To add the names into a list do the following inside the forEach():
list.add(v["name"]);
print(list);
I'm trying to run a chat app using ionic and I'm getting this message
[19:55:51] typescript: src/pages/chat/chat.ts, line: 26
Property 'subscribe' does not exist on type 'AngularFireList<{}>'.
L25: this.username = this.navParams.get('username');
L26: this._chatSubscription = this.db.list('/chat').subscribe( data => {
L27: this.messages = data;
[19:55:51] typescript: src/pages/chat/chat.ts, line: 37
Property 'catch' does not exist on type 'PromiseLike<void>'.
L36: // message is sent
L37: }).catch( () => {
L38: // some error. maybe firebase is unreachable
can anybody help me?
You need to specify valueChanges() or snapshotChanges() before you subscribe.
valueChanges() Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the method provides only the data.
snapshotChanges() Returns an Observable of data as a synchronized
array of AngularFireAction[].
You can read more about retrieving data here
So your code should look like this:
this.db.list('chat').valueChanges().subscribe(data => {
this.messages = data;
});