Query Nested Object in Firebase Firestore - javascript

I have in my Firestore database a list of documents that include this field 'Participants', as a nested object.
I want to make a query that gets only one document from the database (to see if it exists or not) that has (for example) user id 5 and 6.
This is what my code looks like
const chatsCollection = db.collection('chats');
async function createChat(myId, otherUserId){
chat = await chatsCollection
.where(`participants.${myId}`, "==", true)
.where(`participants.${otherUserId}`, "==", true)
.limit(1).get();
if(!chat.exists){
alert('chat doesnt exist')
//create chat
} else {
alert('chat exists')
//do something else
}
}
However, even if the chat with the participants object does indeed exist in the database, the result of the code indicates that it doesn't.
Here is the structure of the data when it is added to the database
var chat_key = (Math.random() + 1).toString(36).substring(2);
chatData = {
key: chat_key,
created_at: new Date(),
participants: {
myId: true,
otherUserId: true,
}
}
chatsCollection.doc(chat_key).set(chatData);
I appreciate any help on how to solve this problem.
Thanks :)

on method collection, you can use empty property to see if the query getting data or not
if(chat.empty){
alert('chat doesnt exist')
//create chat
} else {
alert('chat exists')
//do something else
}
to get only one document from your query, you can use
chat.docs[0].data();

Related

Firestore setDoc Function not merging new items on React JS

so I'm trying to have this function "Walletwrite" check if a document already exists, then if document doesn't exist, creates a new one with the values I want to add, or updates an existing document by adding a new field with those new values. All of this on React JS.
However, my setDoc function is actually overwriting existing data if document already exists..
Any ideas on where the problem is?
async function Walletwrite() {
//These first 2 consts check if the entry is already in that specific document to prevent duplicates.
const marketRef = db.collection("marketplace");
const query = marketRef.where("wallet", "array-contains", account).where("item", "==", item.id).limit(1);
query.get().then((snapshot) => {
if (snapshot.empty == false) {
console.log(snapshot)
return
}
else{
//This is where it gets tricky and merge: true is not working
const walletRef = doc(db, 'marketplace', item.id);
setDoc(walletRef, {item: item.id, wallet: account} , { merge: true });
}
});
}
Trying different firestore functions but none of them seem right to my use case, except this setDoc with merge: true..

get values from firestore query

I have this function:
firestore.collection('customers').doc(userID).collection('subscriptions')
.where('status', 'in', ['trialing', 'active']).get()
.then(activeSubscriptions => {
// if this is true, the user has no active subscription.
if (activeSubscriptions.empty === true) {
console.log("line 31")
{signOut(props.history)}
subStatus = "inactive"
}
});
Basically, in firestore, I have a customers collection, a doc with the user id, and then the subscriptions collection in which is created upon a user processing stripe. In the subscriptions collection, it has a doc which is the subscription id, and I have some fields I want to grab. See the attached picture:
I want to grab the current_period_end data so I can put it out on screen. how would I do this?
If you are looking to access fields from a firestore document, you can do it by specifying the field in square brackets.
With a firestore structure like /customer/cus123/subscriptions/sub123 I was able to obtain a timestamp field of sub123 with this code:
let cusRef = db.collection('customer').doc('cus123').collection('subscriptions').doc('sub123');
cusRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
}
else
{
console.log('Name: ',doc.data()['name']);
console.log('Tmsp: ',doc.data()['tmsp123']);
}
});
I hope you find this useful.

How do to retrieve all documents in a collection and see if a document exists in firebase Firestore?

Schema:
This is how my schema looks
Current Implementation:
for (let i=0; i<data.length; i++) {
try
{
var ifPresent = db.collection("Safes-Hardware").doc(data[i]['Mac address Check']);
ifPresent.get()
.then(async (doc)=>{
if (!doc.exists)
{
// Do stuff
}
else
{
//Do stuff
}
return { message: "Success is within the palm of our hands." }
}
}
Problem:
Even though this code does the job, for each data in the array I'm doing a lookup, and this results in a socket hang-up.(sometimes)
So I'm thinking I'll get all the documents in the collection in one go, store it locally and look up if a documents exists locally instead of querying the database every time.
Question:
How do I implement this?
You can just use collection("Safes-Hardware").get().then() and you can save the data locally.
let collection = []
db.collection("Safes-Hardware").get().then(function(querySnapshot) {
collection = querySnapshot.map((doc) => ({
id: doc.id,
...doc.data()
}))
});
then you can use collection to search for what you want, maybe like this
data.forEach( doc => {
let x = collection.find(v => v.id === doc['Mac address Check'])
if(x){
//it exists
}else{
// not exists
}
})
But take care you are compromising bandwidth or number of requests with o(n^2) operation in the client side

Unable to retrieve data from Cloud Firestore using queries

I am attempting to retrieve a collection of data from my Cloud Firestore, so that I can arrange the data in a "Bootstrap" Table, displaying the name and the score from the Firestore documents.FireStore Layout Here.
I have created a reference to the user collection and queried this to obtain data, however when I run this it throws an exception "Uncaught ReferenceError: querySnapshot is not defined".
<script>
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.orderBy("score", "desc").limit(10); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //If query is needed
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
querySnapshot.docs.map(function (documentSnapshot) {
var name = documentSnapshot.data().name;
var score = documentSnapshot.data().score;
console.log(name + score);
});
}
});
</script>
My aim is to retrieve all of the documents inside the user collection, order and sort them using the inbuilt .limit and orderBy methods, then store them in an array so that they can be displayed using a "Bootstrap" table.
var query = usersCollectionRef.orderBy("score").limit(10); //Selects the 10 highest scoring player's documents
Note for potential readers: the fist part of the answer corresponds to the initial question of the OP, before it was edited.
You have to put the second part of your code within the then() function, as below.
This is because get() returns "a promise that will be resolved with the results of the query." (see the Ref https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#get)
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.where("name", "==", "Steeve"); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //Call get() to get a QuerySnapshot
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
querySnapshot.docs.map(function (documentSnapshot) {
//Not necessary to do that -> return documentSnapshot.data();
console.log(documentSnapshot.data().name);
});
}
});
EDIT following your comment:
In case you would have several documents for a given name which hold a different score (in a number field score), you could get the total score like that:
var usersCollectionRef = db.collection("users"); //Creates a reference to the Users collection
var query = usersCollectionRef.where("name", "==", "Steeve"); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //Call get() to get a QuerySnapshot
var score = 0;
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
var data = querySnapshot.docs.map(function (documentSnapshot) {
//Not necessary to do that -> return documentSnapshot.data();
console.log(documentSnapshot.data().name);
score += documentSnapshot.data().score;
});
}
console.log(score);
});
EDIT after edit of the original post
Do like that
var query = usersCollectionRef.orderBy("score", "desc").limit(10); //Creates a query based on the collection
query.get().then(function(querySnapshot) { //If query is needed
if (querySnapshot.empty) { //Check whether there are any documents in the result
console.log('no documents found');
} else {
var nameArray = Array.from(querySnapshot.docs, x => x.data().name);
console.log(nameArray);
var scoreArray = Array.from(querySnapshot.docs, x => x.data().score);
console.log(scoreArray);
}
});
Explanations:
querySnapshot.docs returns "An array of all the documents in the QuerySnapshot." (See Ref: https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot#docs)
Then you use Array.from() to create the two arrays (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)

Conditional statement to check if user exists in JSON file (or mongoDB)

Background
The JSON file is being generated from a mongoDB with mongoose ODM. However it difficult for me to add a mongoose query to the if statement as I get alot of errors.
The JSON Approach
Using this approach, I cache the mongoDB collection to a JSON file, the attempt to read off the ids.
I have a mods.json file which looks like this (Array Of Objects):
[
{
"userid": "58258161"
},
{
"userid": "135207785"
},
{
"userid": "268339963"
},
{
"userid": "210152609"
}
]
The JSON file above contains a list of users who are allowed to execute a certain Telegram Bot command.
var config = require('./config.json');
var mods = require('./mods.json');
bot.onText(/\/test/i, function (msg) {
var fromId = msg.from.id;
var chatId = msg.chat.id;
for (index in mods) {
if (fromId == config.owner || mods[index].userid) {
console.log('You Are A Mod!');
} else {
console.log('Not A Mod');
bot.sendMessage(chatId, 'You are not a mod');
}
}
});
A brief explanation of how the above is supposed to work:
When the bot receives a "/test" command it is supposed to check if the message is from the owner whose id is stored in the config.json file or any moderator whose unique id is stored in the mods.json file.
The problem
The following code checks through every single id to confirm whether the message is from a mod. And subsequently spits out multiple messages of 'You are not a mod'. Which would be the best method to confirm the user is a mod in the conditional statement 'if'.
The Mongo Approach
When querying with moongose a callback is required, I dont know exactly how to create a if conditional in such a scenario. However this method would obviously be better in such a situation.
You could use Array.some instead, to check if the ID is in the array, that way the message won't be outputted on every iteration, only when it's done checking
var isMod = fromId == config.owner || mods.some(x => fromId == x.userid);
if ( isMod ) {
console.log('You Are A Mod!');
} else {
console.log('Not A Mod');
bot.sendMessage(chatId, 'You are not a mod');
}
Preferably you'd construct a query to ask the database instead, something like
model.find({'mods.userid': config.owner}, function (err, docs) {...

Categories