Inside a Map function, a Firebase query id checker function runs list length number times and halt other operation - android

In my orders list map Function I used another function that checks every order unique id from firebase database that if the id is exists on any document, if it's available then It should put the order item under that reference document if not then in It should create a new reference document and make a new list for that kind of order, but my when It runs inside the loop checking id query runs first and then runs the order placing part, so if fails the checking system
Here is the map function
orderNowList
.map(
(item) => {
orderRequestMaker(
item['title'],
item['product_ref_id'],
item['image_main'],
item['quantity'],
item['price_per_unit'],
item['total_price'],
item['delivery_charge'],
item['buyer_id'],
item['shop_id'],
item['shop_name'],
item['shop_image'],
uniqueId,
),
// removeRequestMaker(item['product_ref_id']),
},
)
.toList(),
Here is the order function
orderRequestMaker(
productName,
productId,
productImage,
productQuantity,
productUnitPrice,
productTotalPrice,
productDeliveryCharge,
buyerId,
shopId,
shopName,
shopImage,
uniqueId) async {
var orderRefId;
QuerySnapshot<Object> currentShopChecker = await FirebaseFirestore.instance
.collection('orders')
.where('ids', isEqualTo: uniqueId)
.get();//first it only runs this query loop limit times, then goes down, but I want
// to run query, get the result and do the rest of the operation
bool statusCheck = currentShopChecker.docs.length == 0;
statusCheck ? orderRefId = '' : orderRefId = currentShopChecker.docs[0].id;
DateTime presentTime = DateTime.now();
if (statusCheck) {
var orderRef = FirebaseFirestore.instance.collection('orders').doc();
orderRefId = orderRef.id;
orderRef.set({
'created_at': presentTime,
'buyer_name': buyerName,
'buyer_id': buyerId,
'ids': buyerId + shopId,
'buyer_image': buyerImage,
'shop_name': shopName,
'shop_id': shopId,
'shop_image': shopImage,
});
}
if (!statusCheck) {
await FirebaseFirestore.instance
.collection('orders')
.doc(orderRefId)
.update({
'created_at': presentTime,
});
}
await FirebaseFirestore.instance
.collection('orders')
.doc(orderRefId)
.collection('order_group')
.doc()
.set({
'created_at': presentTime,
'product_title': productName,
'product_id': productId,
'product_image': productImage,
'product_quantity': productQuantity,
'product_unit_price': productUnitPrice,
'product_total_price': productTotalPrice,
'product_delivery_charge':
productDeliveryCharge != null ? productDeliveryCharge : '',
'buyer_id': buyerId,
'shop_id': shopId,
'status': 'Order placed'
});
}

Related

Future is returning empty List

My below code is returning an empty list, even though it SHOULD return data corresponding to my data stored in my firestore database. Also to note: The otherUserId print statement is not getting printed. How can I fix this issue?
Future<List<String>> getChattingWith(String uid) async {
List<String> chattingWith = [];
try {
// create list of all users user is chatting with
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users', arrayContains: uid)
.get();
for (final room in rooms.docs) {
final users = room['users'] as Map<String, dynamic>;
final otherUserId = users['uid1'] == uid ? users['uid2'] : users['uid1'];
print("otherUserId999: $otherUserId");
chattingWith.add(otherUserId);
}
print("chattingWith: $chattingWith");
return chattingWith;
} catch (error) {
print("error: $error");
return [];
}
}
This part of your code does not match your data structure:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users', arrayContains: uid)
.get();
Your users is a Map and not an array, so arrayContains won't work here. As said in my answer to your previous question, you have to use dot notation to test nested fields:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('users.uid1', isEqualTo: uid)
.where('users.uid2', isEqualTo: otherValue)
.get();
That 👆 is closest to what you tried in your previous question: Firestore conditional array query. It performs an AND condition on the uid1 and uid2 subfields of users.
If instead you want to get all rooms that the user is a participant in, you need an (additional) field that is an array with the UIDs of all participants.
participantUIDs: ["uid1", "uid2"]
Then you can do:
final rooms = await FirebaseFirestore.instance
.collection('rooms')
.where('participants', arrayContains: uid)
.get();

How to retrieve a Map values inside a field of a specific document in firestore using flutter?

I want to get all the Values of the map which is under "Subjects" field. And I also want to listen if any updates or changes made to those values. I actually want to add al those values and store in a variable. Can someone please tell me how can i achieve this?
Here is the structure of the collection.
This is how im adding the subjects whenever a user enters the subject name
onPressed: () async {
temp = qrdataFeed.text;
int index = qrdataFeed.text.indexOf('-');
subject = qrdataFeed.text.substring(0, index);
print("Subject name is $subject");
numberOfClasses = await FirebaseFirestore.instance
.collection('tutors')
.doc(uid)
.get()
.then((doc) async {
Map<String, dynamic> map = await doc.data();
if (!map.containsKey('Subjects')) {
await tutor_details.doc(uid).set({
'Subjects': {'$subject': initialValue},
}, SetOptions(merge: true));
}
if (doc.data()['Subjects']['$subject'] !=
'$subject') {
if (!map.containsKey('$subject')) {
await tutor_details.doc(uid).set({
'Subjects': {'$subject': initialValue}
}, SetOptions(merge: true));
}
}
var val = await doc.data()['Subjects']['$subject'];
return val;
});
if (!mounted) return;
setState(() {
qrData = qrdataFeed.text;
scanned = true;
print('done');
//if (temp != qrdataFeed.text)
numberOfClasses += 1;
print('$numberOfClasses is printed');
});
await tutor_details.doc(uid).set({
'Subjects': {'$subject': numberOfClasses},
}, SetOptions(merge: true));
}
},
Posting the #NisanthReddy's solution as a Community Wiki for visibility.
A better architecture would be to have one class at the root to handle all your transactions and to also notify any listener in your code.
You should always call this class to update and you can add listeners to this class from any widget you want. This way you will have everything Firestore-related in one place.

Can't loop over a map from snapshot retrieved in Firebase Cloud Function

I'm lost with cloud funtions.
I'm trying to read from a table when new entry is written. Then parse some data from this table, and create a new object in a new table.
But I'm lost in some concepts with CF, and node...
At this moment I have the listeners to the table:
exports.createEventInvitation = functions.database
.ref('event/{eventStartDate}/{eventId}/')
.onWrite((change, context) => {
const event = change.after.val();
const eventUsersList = event.userList;
...
})
The object event looks like this:
Event :{ conversationId: '8f6eb2b9-0cbb-4135-b6b6-c9f02c9aa91e',
sharifyEventData:
{ acceptationManual: false,
address: 'ADDRESS FROM USER',
adminProfileImageUrl: 'url_image',
description: 'Description',
eventEmoji: '💬',
finalDate: '2019-11-12',
finalHour: '09:30',
headerImageUrl: '',
initialDate: '2019-11-12',
initialHour: '09:00',
eventType: 'BEER',
title: ''},
eventID: '5f49ff65-bd98-45cb-a554-55da5c3c2f16',
userList: { LeiUlbDlNKWwF6QPgnQiFTE03gt2: true },
userType: 'NORMAL' }
I have to loop over the userlist to check which ID is the owner of the event. But I'm not able to loop it properly.
I tried to get the value like:
const userList = new Map()
const eventUsersList = event.userList
for( var entry in eventUsersList){
if(entry[1]){
userList.set(entry[0],3)
}
}
console.log('UserListInvitation:' + util.inspect(userList, {showHidden: false, depth: null}))
And I achieved something like:
UserListInvitation:Map { 'L' => 3 }
But I'm missing something, because it seems I'm only taken the first letter of the key.
Also I tried:
for( var entryKey in eventUsersList.keys){
if(eventUsersList[entryKey]){
userList.set(entryKey,3)
}
}
And this It's returning nothing
What I'm missing?
If I understood you properly then the following code should work:
const userList = new Map()
const eventUsersList = event.userList
for( var key in eventUsersList){
if(eventUsersList[key]){ // Safety check
userList.set(key, 3) // key-value?
}
}

need some processing to do before cloud function returns a promise. But promise is return before the processing

i have a cloud function where i pass an array of numbers and compare those numbers with collection in the firestore . And if the numbers are present than return an array with those numbers. But before comparing those numbers the function return empty value in the promise.
I've tried using async await but the execution sequence remained same.
//sort contact list
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col=admin.firestore().collection("joshua");
var match:[]
match=data.list
var perm1=new Array()
res11.push("454675556")
console.log("above resolve")
for(let val in match){
var inter=await Promise.all([getValues(col,val)])
console.log("inside resolve"+inter)
}
perm1.push("23432")
console.log("just before resolve")
return new Promise((res,rej)=>{
res(perm1)
})
});
//the async function which is suppose to process on every iteration
function getValues(col1:any,val1:any)
{
return new Promise(async(res,rej)=>{
var query= await col1.where('Listed','array-contains',val1)
var value=await query.get()
res(value)
})
.catch(err=>{
console.log(err)
})
}
i want the sequence to be asynchronous where the return value from getValues is waited upon and inside getValues result of query.get is waited upon.
so that at last return only be sent when all process is finished.
I think this is what you are looking for
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col = admin.firestore().collection("joshua");
var match:[]
match = data.list
var perm1 = []
// res11.push("454675556") // ? undefined
for(let val in match){
var inter = await getValues(col,val)
console.log("inside resolve" + inter)
}
perm1.push("23432") // ??
// console.log("just before resolve")
return Promise.resolve(perm1)
});
const getValues = async (col1:any, val1:any) => {
const query = col1.where('Listed','array-contains', val1)
var value = await query.get().then(getAllDocs)
return value
}
const getAllDocs = function(data: any) {
const temp: Array<any> = []
data.forEach(function (doc: any) {
temp.push(doc.data())
})
return temp
}

Read data from cloud firestore with firebase cloud function?

I'm an Android developer and recently I've started working on a project based on firebase cloud functions and firestore database. I'm writing an HTTP trigger function that will take two parameters and compare that parameter value with the firestore data value and if the value matches then return a response of true or else false.
Duplicate Question:
Yes, there are some question already asked related to mine but they are not similar:
Firestore + cloud functions: How to read from another document
Firebase HTTP Cloud Functions - Read database once
Firebase Docs says:
Cloud Firestore supports create, update, delete, and write events
I want to read firestore value from HTTP trigger.
What I have tried:
exports.userData = functions.https.onRequest((req, res) => {
const user = req.query.user;
const pass = req.query.pass;
});
I'm pretty much stuck at this part. Any help will be greatly appreciated. Thanks
P.S. I have very limited knowledge related to JS/TypeScript/NodeJS
a bit late, but for any one else stumbling upon this.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.someMethod = functions.https.onRequest((req, res) => {
var stuff = [];
var db = admin.firestore();
db.collection("Users").doc("7vFjDJ63DmhcQiEHwl0M7hfL3Kt1").collection("blabla").get().then(snapshot => {
snapshot.forEach(doc => {
var newelement = {
"id": doc.id,
"xxxx": doc.data().xxx,
"yyy": doc.data().yyy
}
stuff = stuff.concat(newelement);
});
res.send(stuff)
return "";
}).catch(reason => {
res.send(reason)
})
});
Thanks to Ruan's answer, here's an example for onCall(..) variation:
exports.fireGetColors = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
var colors = {};
var db = admin.firestore();
db.collection('colors')
.get()
.then(snapshot => {
snapshot.forEach(doc => {
var key = doc.id;
var color = doc.data();
color['key'] = key;
colors[key] = color;
});
var colorsStr = JSON.stringify(colors, null, '\t');
console.log('colors callback result : ' + colorsStr);
resolve(colors);
})
.catch(reason => {
console.log('db.collection("colors").get gets err, reason: ' + reason);
reject(reason);
});
});
});
In 2022, I am trying to do this thing in "Modular" way as what firebase has for version >= 9. Using typescript too as an addition :). Thanks to Ruan for the inspiration.
So, here is how I made it ( similar to the following ):
import * as functions from "firebase-functions";
import { getFirestore } from "firebase-admin/firestore";
import { initializeApp } from "firebase-admin/app";
initializeApp(functions.config().firebase);
export const someMethod = functions.https.onRequest((req, res) => {
let stuff: any[] = [];
let db = getFirestore();
db.collection("Users").doc("7vFjDJ63DmhcQiEHwl0M7hfL3Kt1").collection("blabla").get().then(snapshot => {
snapshot.forEach(doc => {
var newelement = {
"id": doc.id,
"xxxx": doc.data().xxx,
"yyy": doc.data().yyy
}
stuff = stuff.concat(newelement);
});
res.send(stuff)
return "";
}).catch(reason => {
res.send(reason)
})
});

Categories

Resources