React Firestore - Retrieve all documents in an Array of document IDs - reactjs

I am trying to retrieve an all documents of which document ID is within the given array. I have no issues retrieving the list of documentIDs and storing in the array. However, I am not sure on how to retrieve the documents of which ids are in the array. Please help Thanks!
portfolio doc:
docId{
docId: docId,
...
}
const getData = (bookmarkIds) => {
console.log("this is " )
console.log(bookmarkIds)
console.log("entering" )
const portfolioQuery = database.portfolioRef.where("docId", 'in', bookmarkIds);
portfolioQuery.onSnapshot((snapshot) => {
console.log(snapshot.docs)
if (snapshot.docs.length !== 0) {
var id = 1;
const tempItem = [];
snapshot.docs.forEach((doc) => {
tempItem.push({
id: id,
intervieweeName: doc.data().intervieweeName,
intervieweeEmail: doc.data().intervieweeEmail,
projectTitle: doc.data().projectTitle,
portfolioTitle: doc.data().portfolioTitle,
dateCreated: doc.data().dateCreated,
fbId: doc.id
})
id++;
})
setPortfolioData(tempItem)
}
})
}
useEffect(() => {
const getUserData = database.usersRef.where("email", "==", currentUser.email);
const bookmarkArray = [];
const unsub = getUserData.onSnapshot((snapshot) => {
snapshot.docs.forEach((doc) =>{
bookmarkArray.push(doc.data().bookmarkIds);
})
console.log(bookmarkArray);
getData(bookmarkArray)
})
return unsub;
}, [currentUser.email]);
Based on my current code above, I am receiving the following (Not getting any error just a blank return):

I realised I made a double array by doing
bookmarkArray.push(doc.data().bookmarkIds);
solved by doing
bookmarkArray = doc.data().bookmarkIds;

Related

react firestore sub collection

How can I get a list of cars for a customer
clients:
w21rffa3:
name: Johny
phone: 123123
cars:
fn1jnr12:
brand: AUDi
model: a6
number: 24f1
dsdasgf122:
brand: AUDi
model: a3
number: 62s14
My code
const ref = firestore().collection('clients');
const [clientsList, setClientsList] = useState([]);
useEffect(() => {
return ref.onSnapshot(clientsSnapshot => {
const clients = [];
const cars = [];
clientsSnapshot.forEach(client => {
const carsRef = ref.doc(client.id).collection('cars').onSnapshot(carsSnapshot => {
carsSnapshot.forEach(car => {
if (car.data().brand.length > 0) {
const {
brand,
model,
number
} = car.data();
cars.push({
id: car.id,
brand,
model,
number,
});
}
});
//Good result`
console.log('After forEach: ', cars);
});
//Bad result
console.log('After snapshot: ', cars);
const {
name,
phone
} = client.data();
clients.push({
id: client.id,
name,
phone,
cars: cars,
});
});
setClientsList(clients);
});
}, []);
cars list for customers
The error you facing is due to misuse/misunderstanding of how async/callback-based functions works. As I said in my comment - good result and bad result - bad result scripts are executed before good result due to onSnapshot is async, and you pass a callback function to it, which will be executed when data is available from firebase, so a bit "later" than the rest of the code.
Now about what can be done. The code is a bit tricky and I didnt really test it, so if anything - please, let me know.
const [clientsList, setClientsList] = useState([]);
useEffect(() => {
let carsUnsubscribeFns = [];
const clientUnsubscribeFn = ref.onSnapshot((clientsSnapshot) => {
// Reset everything and stop previously created listeners for Cars
setClientsList([]);
carsUnsubscribeFns.forEach((x) => x());
carsUnsubscribeFns = [];
clientsSnapshot.forEach((c) => {
const { name, phone } = c.data();
const client = { id: c.id, name, phone };
// In case you dont want to use optional chaining,
// remove the const client = ... line above
// and uncomment the line below
// but optional chaining is prefered anyway
// const client = { id: c.id, name, phone, cars: [] };
const carsUnsubscribeFn = ref
.doc(client.id)
.collection("cars")
.onSnapshot((carsSnapshot) => {
// Mutate the Client object directly
client.cars = carsSnapshot.docs
.map((x) => ({ id: x.id, ...x.data() }))
.filter((x) => x.brand?.length > 0);
// mark ClientsList as updated to force a rerender
// due to we mutated one of the entities inside
setClientsList((curr) => [...curr]);
});
carsUnsubscribeFns.push(carsUnsubscribeFn);
setClientsList((curr) => {
curr.push(client);
return [...curr];
});
});
// clean-up function returned from hook to stop all the listeners
return () => {
[clientUnsubscribeFn, ...carsUnsubscribeFns].forEach((x) => x());
};
});
}, []);

I can't access one of two subcollections in firestore data base. React

I have two subcollections inside the same document
I am able to access the first one with this code:
useEffect(() => {
const getData = () => { // get data from firestore to app
const q = query(collection(db, `lists/my lists/${currentList}`), orderBy('queryPreference'));
onSnapshot(q, (snapshot) => {
firestoreList = []; // reset firestoreList after every change to avoid copies in items array
firestoreIds = [];
snapshot.docs.forEach((doc) => {
console.log('subcol item', doc)
firestoreList.push({ ...doc.data(), id: doc.id });
firestoreIds.every(id => id !== doc.id) && firestoreIds.push(doc.id);
});
if (firestoreList.length === 0) {
setItems(items.concat(newItem));
} else {
setItemIds(firestoreIds);
setItems(firestoreList);
}
});
}
getData();
console.log('get data test')
}, [currentList]);
where currentList is hard coded to 'shopping list'. If i change currentList to 'to do list' firebase doesn't return anything (no errors either). Both names and ids of of both collections are spelled as above: 'shopping list' and 'to do list'.
It should be like this:
const q = query(collection(db, 'lists', 'my lists', currentList),
orderBy('queryPreference'));

Update an array relation belongs to many with Strapi controller

I use Strapi V4. I have a link collection and I want to update likes.
How update the relation array ? When I put new data old value are replace by the new one.
Example :
likes : [1]
if I update another time
likes:[2].
BUT I want this likes : [1,2]
I try this but It d'oesn't work. Thans for your replay
'use strict';
/**
* link controller
*/
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::link.link', ({ strapi }) => ({
// Method 2: Wrapping a core action (leaves core logic in place)
async find(ctx) {
const { data, meta } = await super.find(ctx);
const linkId = data.map((link) => link.id);
const allPosts = await strapi.entityService.findMany('api::link.link', {
fields: ["id"],
filters: { id: { $in: linkId } },
populate: {
likes: { count: true },
},
});
data.forEach(link => {
link.likes = allPosts.find(({ id }) => id === link.id)?.likes?.count || 0;
});
//update value with new array => need to be fix
await strapi.entityService.update("api::link.link", {
likes: [...allPosts.likes.map(({ id }) => id), ...likes],
});
return { data, meta };
},
}));
This part need to be fix. Can you help me ? Thanks
//update value with new array => need to be fix
await strapi.entityService.update("api::link.link", {
likes: [...allPosts.likes.map(({ id }) => id), ...likes],
});

How to implement the fetching of data for different categories of products to be shown in a home page using firebase on a Reactjs project

I want to get the products across different categories to be shown on the home page. The below code only fetches data from a single category. How do I go about fetching products from multiple categories. Should I use promises ? I feel like there will be a lot of redundant code. Is there a better way?
fetchProducts = async ( category )=>{
let productsRef = projectFirestore.collection("products");
let query = productsRef;
query = productsRef.where('category', '==', 'Beverage');
query.get().then((querySnapshot) => {
let products = [];
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
products.push({
name : doc.data().name,
price : doc.data().price,
prev_price : doc.data().prev_price,
discount : doc.data().product_discount,
id : doc.id,
src : doc.data().pictures[0].src,
rating: doc.data().rating
});
});
this.setState(() => {
return { products };
}, this.checkCartItems);
})
Edit: Here's the correct solution: docs - https://firebase.google.com/docs/firestore/query-data/queries#in_not-in_and_array-contains-any
fetchProducts = async (categories) => {
let productsRef = projectFirestore.collection("products");
let query = productsRef.where('category', 'in', categories);
query.get().then((querySnapshot) => {
let products = [];
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
products.push({
name: doc.data().name,
price: doc.data().price,
prev_price: doc.data().prev_price,
discount: doc.data().product_discount,
id: doc.id,
src: doc.data().pictures[0].src,
rating: doc.data().rating,
});
});
this.setState(() => {
return { products };
}, this.checkCartItems);
})
.catch(err => console.log(err));
};

How to Verify if each element the Array contains the search string in Typescript/protractor

How do i Verify if each element of the Array contains the search string in Typescript/ Protractor??
All the console statements returned false as they were looking for complete text rather than a search string. Please suggest a solution.
arr = [ 'Citibank, N.A.', 'Citi China Companies', 'Citibank Ireland' ]
search string = 'citi'
Then('I enter search text where the highlighted search results will include a Client Company Name {string}, {string}', async (searchText, companyName) => {
await acctmgrclientselection.deleteSearchText().then(async () => {
await acctmgrclientselection.getSelectClientSearchInputEl().sendKeys(searchText).then(async () => {
await acctmgrclientselection.getSelectClientSearchInputEl().sendKeys(protractor.Key.ENTER).then(async () => {
await dashboardFilter.getEmployeeListGrid().count().then( async ( CountVal ) => {
if(CountVal >1)
{
var strArr: Array<string> = [];
await acctmgrclientselection.getClientTblCompanyName().getText().then(async (text) => {
await strArr.push(text)
//strArr.forEach(function(value){
var sortable = [];
strArr.forEach(value => {
sortable.push([value]);
let sorted_array: Array<string> = sortable.map(arr => arr[0])
let result = sorted_array.every(element => element.includes(searchText))
console.log(result)
});
});
}
else
{
//clear criteria
console.log('clear criteria');
await element(by.cssContainingText('mat-card.empty-results.mat-card p','0 results matching your criteria')).isDisplayed().then(async()=>{
await element(by.cssContainingText('mat-card.empty-results.mat-card a','Clear Criteria')).isDisplayed();
});
}
});
});
});
});
});
You need to check for the regex with search string.
const pattern = new RegExp("Citi");
const result = sorted_array.every(element => pattern.test(element));
console.log(result);

Resources