Martin
Martin

Reputation: 1219

Flutter Firestore Update Where

I'm trying to run a query that retrieves a single row given a where clause and updates it. I understand that Firebase doesn't support an UpdateWhere operations so I'm trying to use a Transaction instead.

I'm having difficulty making it work, maybe I'm too used to sql dbs... Here's my broken code

try {
    final whereQuery = _db
        .doc(userPath(user))
        .collection("someInnerCollection")
        .where("active", isEqualTo: true)
        .limit(1);

    await _db.runTransaction((transaction) async {
        final entry = await transaction.get(whereQuery);  // This doesn't compile as .get doesn't take in a query
        await transaction.update(entry, {
            "someValue": "newValue",
        });
    });
} catch (e) {
    ...
}

Upvotes: 1

Views: 3054

Answers (3)

Rogelio Monter
Rogelio Monter

Reputation: 1222

From the test I’ve made, I would suggest the following to achieve what you mention:

Based on the following answer:

As you can see from the API documentation, where() returns a Query object. It's not a DocumentReference.

Even if you think that a query will only return one document, you still have to write code to deal with the fact that it could return zero or more documents in a QuerySnapshot object. I suggest reviewing the documentation on queries to see examples.

After doing the query consult, you have to get the DocumentReference for that given result.

Then, you can use that reference to update the field inside a Batched writes

try {
    final post = await firestore
        .collection('someInnerCollection')
        .where('active', isEqualTo: true)
        .limit(1)
        .get()
        .then((QuerySnapshot snapshot) {
            //Here we get the document reference and return to the post variable.
            return snapshot.docs[0].reference;
        });

    var batch = firestore.batch();
    //Updates the field value, using post as document reference
    batch.update(post, { 'someValue': 'newValue' }); 
    batch.commit();
    
} catch (e) {
    print(e);
}

Upvotes: 4

adamcapjones
adamcapjones

Reputation: 193

You can use a collection reference and then update single fields using .update().

final CollectionReference collectionReference = FirebaseFirestore.instance.collection('users');

await collectionReference.doc(user.uid).collection('yourNewCollection').doc('yourDocumentInsideNestedCollection').update({
        'singleField': 'whatever you want,
      });

Same code using "where"

collectionReference.doc(user.uid).collection('yourNewCollection').doc().where('singleField', isEqualTo: yourValue).update({
            'singleField': 'whatever you want,
          });

Upvotes: -1

Dharmaraj
Dharmaraj

Reputation: 50930

You are passing the DocumentSnapshot back in the update() operation instead of DocumentReference itself. Try refactoring the like this:

final docRefToUpdate = _db.collection("colName").doc("docId");

await _db.runTransaction((transaction) async {
  final entry = await transaction.get() // <-- DocRef of document to update in get() here
  await transaction.update(docRefToUpdate, {
    // Pass the DocumentReference here ^^
    "someValue": "newValue",
  });
});

Upvotes: 0

Related Questions