Baffled by firestore uneven segments error - flutter

I'm trying to get some data into a firestore collection from a flutter app like so:
onPressed: () {
_uid = _controller.text.trim();
Firestore.instance.collection('UserData').document(_uid)
.setData({
'uid': _uid
})
.then((_) {
print("user added to UserData");
}).catchError((e) {
print("add UserData err: $e");
});
},
But this gives the following error:
add UserData err: PlatformException(error, Invalid document reference. Document references must have an even number of segments, but UserData has 1, null)
This is weird since I have a simple coll/doc pair. I'm using the same code structure I'm multiple other places with no problem. Here's how the db looks like:
Someone please help me sort this out?

It sounds like _uid is an empty string. You'll have to figure out why that is, and check for that case before using it in a document reference.

Related

How to update all collection in firebase firestore in flutter

I have two collections. One collection "User", who contains the user info (name...) And one collection "Post" who contains all posts of my flutter application. A post document contains many fields like a "Title", "Name" of the user. I add an option in my application to allow the user to change his name. But I must change the name in the "User" collection and in all posts it creates in the "Post" collection. How should I do it? Can anyone help me with an example?
There's nothing magical here. You'll need to get all post documents for that user with a query, and then update them one by one or in batches.
I'd also recommend checking out: What is the fastest way to write a lot of documents to Firestore?
Depends on which firestore are you using.
For Cloud Firestore:
You can update like this way, this is the case where you are updating just one field of your user.
final docRef = db.collection("users").doc("user_id");
final updates = <String, dynamic>{
"timestamp": FieldValue.serverTimestamp(),
};
docRef.update(updates).then(
(value) => print("DocumentSnapshot successfully updated!"),
onError: (e) => print("Error updating document $e"));
For updating a nested field:
// Assume the document contains:
// {
// Title: "Post Tittle",
// Name: "Post Name"
// user: { id: "1", name: "User Name" }
// date: "2022-12-08"
// }
db
.collection("posts")
.doc("post_id")
.update({"date": "2022-13-08", "user.name": "New name"});
You can see more details here: https://firebase.google.com/docs/firestore/manage-data/add-data
Assuming there is a user id attached to each post, you can query from the posts collection where the user (that is changing his/her name) id matches the id that is in the post (from the posts collection) and then modify the user property/attribute from the results.
A sample code would look like this,
To modify from the user collection
final docRef = FirebaseFirestore.instance
.collection('users')
.doc(id);
final response = await docRef
.update(updatedDateInJson)
.then((value) => value)
.onError((error, stackTrace) => error);
To modify from the posts collection where the user is found in a post
final response = FirebaseFirestore.instance
.collection('posts')
.where('name', isEqualTo: 'John')
.get()
.then((value) async {
// modify each doc
});
Quick Note: use a onError block to check for errors in updating docs.

Flutter & MongoDb Error: 'The method '[]' was called on null. Receiver: null Tried calling: []("id"))'

I am new to coding. I was following the course and I get an error that I don't know how to solve.
I want to create a user and then I want to create a task associated with this user. Both, the user and the task get created - I can see it in mongodb. Somehow the userid for this newly created task ends up being null and I get 'The method '[]' was called on null. Receiver: null Tried calling: )' error. Again, user id is created - I can see it in mongodb. I suspect something is wrong with the way I try to retrieve userId
This is how I retrieve the userId:
child: Mutation(
options: MutationOptions(
document: gql(insertTask()),
fetchPolicy: FetchPolicy.noCache,
onCompleted: (data) {
print(data.toString());
setState(() {
_isSaving = false;
currUserId = data['createUser']["id"];
});
},
),
Please advise, I suspect it may be something silly, but I can't get my head around it.

Flutter - Can't get collection from firestore

_getLatestCompletedWorkout() async {
try {
QuerySnapshot workouts;
workouts = await FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.collection('workouts')
.get();
for (var workout in workouts.docs) {
print('WORKOUT = ');
print(workout);
}
.....
What I really need is to get the last document saved; but before that I am just trying to fetch the "workouts" collection; the workouts.docs list always has 0 items. There are 2 items in the DB. What is wrong with this code? Also how to get the last saved item?
As mentioned by Frank :
You can refer Alex answer here :
The simplest way to achieve this is to add a date
property to each object in your collection, then simply query it
according to this new property descending and call limit(1) function.
This is the required query:
this.historyRef = afs.collection<History>('history', ref => ref.orderBy('date', 'desc').limit(1));
this.history = this.historyRef.snapshotChanges().map(actions => {
return actions.map(a => {
const data = a.payload.doc.data() as Hisotory;
const docId = a.payload.doc.id;
return { docId, ...data };
});
});
This has been found since cloud_firestore updates that prevent app that not regiter in App Check to take updates seriously "but it store it with lighter id color" which Protect your Cloud Firestore resources from abuse, such as billing fraud or phishing
Kindly check and ensure your app is registered inside App Check in Firebase console

Adding a column and updating all records using knex and postgres

I need to add a column to my table of riders, allowing us to store the name of the image that will display on that rider's card. I then need to update all of the records with the auto-generated image names.
I've done a bunch of searching, and all roads seem to lead back to this thread or this one. I've tried the code from both of these threads, swapping in my own table and column names, but I still can't get it to work.
This is the latest version of the code:
export async function up(knex, Promise) {
return knex.transaction(trx => {
const riders = [
{
name: 'Fabio Quartararo',
card: 'rider_card_FabioQuartararo'
},
...24 other riders here...
{
name: 'Garrett Gerloff',
card: 'rider_card_GarrettGerloff'
},
];
return knex.schema.table('riders', (table) => table.string('card')).transacting(trx)
.then(() =>{
const queries = [];
riders.forEach(rider => {
const query = knex('riders')
.update({
card: rider.card
})
.where('name', rider.name)
.transacting(trx); // This makes every update be in the same transaction
queries.push(query);
});
Promise.all(queries) // Once every query is written
.then(() => trx.commit) // We try to execute all of them
.catch(() => trx.rollback); // And rollback in case any of them goes wrong
});
});
}
When I run the migration, however, it fails with the following error:
migration file "20211202225332_update_rider_card_imgs.js" failed
migration failed with error: Cannot read properties of undefined (reading 'all')
Error running migrations: TypeError: Cannot read properties of undefined (reading 'all')
at D:\Users\seona\Documents\_Blowfish\repos\MotoGP\dist\database\migrations\20211202225332_update_rider_card_imgs.js:134:25
at processTicksAndRejections (node:internal/process/task_queues:96:5)
So it's clearly having some sort of problem with Promise.all(), but I can't for the life of me figure out what. Searching has not turned up any useful results.
Does anyone have any ideas about how I can get this working? Thanks in advance.
I think you might be following some older documentation and/or examples (at least that's what I was doing).
The Promise argument is no longer passed into the migration up and down functions.
So, the signature should be something like this:
function up(knex) {
// Use the built in Promise class
Promise.all(<ARRAY_OF_QUERY_PROMISES>);
...
}

FireStore: How to merge timestamp data to existing document?

I am new to FireStore and and building an app where users can bookmark photo documents and show them on their personal feed. This works fine. Now, I want to be able to sort the bookmarks by bookmarked date when the user is viewing their personal feed (orderBy method). Thus, to make this happen, I figured I'd add a timestamp value at the moment the user bookmarks the document.
Here's my attempt. I wanted to verify with the community whether this is a good way to do it. I am concerned about redundancy and extra writes.
async addDocToFeed({state}, doc) {
try {
const feedRef = this.$fireStore
.collection(`users/${state.userProfile.uid}/feed`)
.doc(doc.id)
await feedRef.set(doc) < --- copy record to user's feed collection (see json sample below)
const bookmark = this.$fireStore
.collection(`users/${state.userProfile.uid}/feed`)
.doc(doc.id)
bookmark.update({
bookmarked: this.$fireStoreObj.FieldValue.serverTimestamp()
})
// })
console.log('doc bookmarked')
} catch (error) {
console.error('error updating doc', error)
}
}
Example JSON of doc before adding the timestamp:
{"id":"1KecNCqYlcVRjq4BLCbZ","comments":"__vue_devtool_nan__","url":"https://firebasestorage.googleapis.com/v0/b/vue-photoapp-api.appspot.com/o/photos%2F0.jpg?alt=media&token=ee23b95b-b5d8-4abe-b1b9-e335d591b413","tags":["router","Texas"],"filename":"0.jpg","description":"test with new router setup","createdAt":{"seconds":1596020630,"nanoseconds":473000000},"title":"test with new router setup","status":"Unsolved","userId":"SvuTxDtHXJdBHImNQWByqnO3F2U2","displayName":"MrRouter"}
I tried to do:
await feedRef.set({doc, bookmarked: this.$fireStoreObj.FieldValue.serverTimestamp()}, {merge: true})
but that erased all the data and only added the bookmarked timestamp.
Thanks for any advice or assurances I'm on the right track (or not)
this
.$fireStore
.collection(users/${state.userProfile.uid}/feed)
.doc(doc.id);
.set({
bookmarked: Date.now()
}, {merge: true})
.then(() => {
resolve(true);
}).catch((error) => {
reject(error)
})
This should work.