Delete object from list via firebase rest api - firebase

Currently I can't seem to find a way to delete an object from firebase list via REST api. For example I am trying to remove this from the list:
https://mrdapper.firebaseio.com/v0/users/41/favs.json?orderBy=%22id%22&equalTo=107657061
Posting a DELETE request doesn't work with query parameter.

You can't delete with a query, (although that would be awesome). But you can use the results to send a DELETE request.
Do a GET:
GET https://mrdapper.firebaseio.com/v0/users/41/favs.json?orderBy=%22id%22&equalTo=107657061
This will return the object and you can send a DELETE request for each item it returns.
DELETE https://mrdapper.firebaseio.com/v0/users/41/favs/<returned-id>.json
Now, you may not like sending one delete request per object. But, with your data structure this is necessary.
If you'd like to easily query and delete items, you could try this data structure:
/users/$user_id
/userFavs/$user_id/$fav_id
Store the favs in it's own location under the root. This will allow you to retrieve user data without always getting the favs.
For userFavs if you key off userid and the favid you can easily query and delete.
{
"userFavs": {
"41": {
"107657061": {
"note_count": 43633
}
}
}
}
Now you can easily get all of the the user's favorites by specifying the user's id. If you need to delete by an id, that is also a key. So you can now DELETE without querying.
DELETE https://mrdapper.firebaseio.com/v0/userFavs/41/107657061.json

Related

How to create one stream listening to multiple Firestore documents created from list of documents references in Flutter

Im trying to create one stream, that is using multiple documents references that are stored and fetched from Firebase Firestore.
Lets say I have two collection named users and documents. When user is created he gets document with his id in users collection with field named documentsHasAccessTo that is list of references to documents inside documents collection. It is important, that these documents can be located in different sub collections inside documents collection so I dont want to query whole documents and filter it, in order to save Firestore transfer and make it faster I already know paths to documents stored in documentsHasAccessTo field.
So for example, I can have user with data inside users/<user uid> document with documentsHasAccessTo field that stores 3 different document references.
I would like to achieve something like this (untested):
final userId = 'blablakfn1n21n4109';
final usersDocumentRef = FirebaseFirestore.instance.doc('users/$userId');
usersDocumentRef.snapshots().listen((snapshot) {
final references = snapshot.data()['documentsHasAccessTo'] as List<DocumentReference>;
final documentsStream = // create single query stream using all references from list
});
Keep in mind, that it would also be great, if this stream would update query if documentsHasAccessTo changes like in the example above, hence I used snapshots() on usersDocumentReferences rather than single get() fetch.
The more I think about this Im starting to believe this is simple impossible or theres a more simple and clean solution. Im open to anything.
You could use rxdart's switchMap and MergeStream:
usersDocumentRef.snapshots().switchMap((snapshot) {
final references = snapshot.data()['documentsHasAccessTo'] as List<DocumentReference>;
return MergeStream(references.map(ref) => /* do something that creates a stream */));
});

Deleting data that all users use but only for one user in Cloud Firestore

I am trying to structure my data such that when someone adds a new product to the database, all users receive the new product in their list and therefore the new product appears on their screen.
But if a user decides to delete that product, they can delete it but only for themselves. Is there a Cloud Firestore sorting/ordering/filtering that I should be using to accomplish this?
I thought I could use something like the following:
final theProduct = Provider.of<Products>(context);
products = await firestore.collection('products').getDocuments()
for (product in products.documents) {
await firestore.collection('products').add({
'nameOfProduct': theProduct.nameOfProduct
});
}
But I get a document property error.
Maybe I need to go in one more collection and then try something? But I also need to be able to retrieve the data back using the userID of the signed in user..
Any hints/helpful links would be greatly appreciated.
So I think what I want to do is iterate through all documents within a collection and then document().collection('').add() something to each of their collection. Hopefully that sheds some more light on my problem.
Thanks to those who commented. I found a way to implement this was to use the unique value that each product contains and add it to a list on a per user basis in Firestore. Then fetch that list from Firestore and filter out the corresponding products. No deleting necessary.
Question : a user decides to delete that product, they can delete it but only for themselves
Answer: U can create list in user profile section where u can have all the product document ids & u can use that document id to fetch particular product details & when user click on delete button u can remove that particular document id from there collection
Im not sure what r u doing with sample code over there.
If u want to add data to database then use :
await Firestore().collection('Products').add({
'nameOfProduct': theProduct.nameOfProduct,
});
this will generate document random id for your product.
To get data from particular id use :
DocumentSnapshot documentSnapshot = await Firestore().collection('Products').document('document').get();
then u can use that document snapshot to get data for particular key e.g.
documentSnapshot.data['Product Name']

Index error in query in Firebase

I'm having trouble setting up a search query within my Firebase database. I put the rules all the way of my search, but I always get the index error.
Below is my structure:
My Firebase database structure:
My query:
https://zoome-production-users.firebaseio.com/country.json?orderBy="fullname"&equalTo="Vitor Darela"
Erro:
{
"error": "Index not defined, add \".indexOn\": \"fullname\", for path \"/country\", to the rules"
}
In your REST call, you run a query on /country in your database. This query inspects each direct child node of /country to see if it matches your filter. In your JSON data /country/AD does not have a property fullname, so the query will not return anything. Even if you were to add the index that the error message tells you about, it will not return anything.
The query you are trying to do is not possible with your current data structure. You will need to modify your data structure to allow it. It seems that you're trying to to find the countries that have a user with a certain name. To allow that query, add an additional data structure that holds precisely that:
"countries_by_fullname": {
"Vitor Darela": {
"AD": true
}
}
With this additional structure you can find the list of countries by simply reading /countries_by_fullname/Vitor Darela.
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value

How to retrieve Node names in Firebase without iterating through the snapshot

My data looks like below,
"USERS": { "JACK": { "FirstName":"Jack", "LastName":"Wil" }, "JAY": { "FirstName":"Jay", "LastName":"Martin" } }
I'm writing a HTTPS triggered cloud function that first sends Node names (JACK, JAY) and then based on selection, sends details.
For sending the Node names, I'm just wondering if there is any way/function to get all the Node names under a Child without iterating through the snapshot and collecting the names using '.key'
I have gone through the below posts, but they discuss the iteration logic. So posting a new question.
Getting node names from Firebase database based on emailId match
Getting node names from Firebase database based on emailId match

Meteor: Disallow user from selecting id's when inserting documents

When using mini-mongo to insert documents into a collection a user could pass the _id field and that _id will be set on the document as long as it is a string or an ObjectID (and doesnt collide with an existing id). That doesnt seem sensible to me. I want the _id of the documents to be generated by the server, always, so I dont end up with a db where both strings (potentially of different length) and ObjectIDs exist as _ids.
Is there a simple way to achieve this? Right now the best I can think of is checking the id in a deny rule (where the _id will either already be set by Meteor or be the value the user provided) and if it's not the type/length I want it to be I change it, but that also requires checks to avoid duplicate ids. Not too difficult but seems overly complex for something as basic as this.
Reviewing my response, here's your answer:
Deny all inserts. Create a method, collectionInsert(document), that checks if an _id field is specified.
Meteor.methods({
collectionInsert: function(document) {
if (document && document._id) {
delete document._id;
}
// Returns the _id generated
return collection.insert(document);
}
});
In today's versions of meteor (0.8 and higher) the server and client generate the same _id in this case anyway. But using this method should ensure that the client simulates the field insert and that the server's version of the generated _id is authoritative.
The correct way to do this is probably to do the insert in a Meteor.method. You can't trust client-generated IDs in high-risk applications, so using collection#insert with allow/deny hooks isn't sufficient. Instead, call a method to do the insert, which will always create a server-generated ID.
You can still stub this method on the client, for latency compensation, but the inserted ID will be overwritten when the server call returns.

Resources