Firestore onSnapshot with "where" and "orderBy" not matching any documents - javascript

I am struggling to figure out why the following code produces the "doc.empty" console log. The screenshot shows what I see in Cloud Firestore's data console. My abbreviated code is below. In my example, I have the following variables:
dataset = '202203aam'
custnum = '19930'
firestoredb.collection('sold').doc(dataset).collection('sold').where('custnum', '==', parseInt(custnum)).orderBy('lot', 'asc').onSnapshot(function(doc){
if (doc.empty){
console.log('doc.empty');
} else {
doc.forEach(function(doc){
//code here
});
}
});
Why would this not match my data?

The problem is here:
.where('custnum', '==', parseInt(custnum))
The screenshot shows that your custnum field has a string value, yet you are explicitly passing a numeric value in the condition. Strings and numeric values are never the same in the database, so the condition doesn't match the document you how.
To make the query work, make sure you pass the value as the same type that you've stored in the database.

Related

Trouble with accessing Firebase Cloud Firestore

I am using Cloud Firestore and am having some problems accessing a value in a simple database.
Here is how the database is structured
This is the code I am using to access the "basementER-status" field in the database.
//current status value is pulled from database
function getRawStatus ()
{
return db.collection("rooms").doc("roomsDoc").get().then(function(doc) {
console.log(doc.data());
console.log(doc.data().basementER-status);
return doc.data().basementER-status;
});
}
For the first console.log, this is printed to the console:
{1ER-status: 0, 2ER-status: 0, basementER-status: 0}
1ER-status: 0
2ER-status: 0
basementER-status: 0
__proto__: Object
This is the correct doc that needs to be brought from the database, so I know that part of my code is right.
However, the second console.log prints NaN to the console.
What is happening here? I don't understand. I've accessed fields like this before in cloud firestore and it has always worked.
For your second console.log statement, you are trying to access a specific parameter in an object, so you should use this:
console.log(doc.data()["basementER-status"]);
For more info, go here: firestore adding data link
The problem is because of the way JavaScript parses your statement. This line:
console.log(doc.data().basementER-status);
Is actually performing a mathematical subtraction between doc.data().basementER and the value of the variable status. That's not what you want.
If you want the value of a field with JavaScript operators or other special characters in it, you will have to use a different syntax:
const data = doc.data();
console.log(data['basementER-status']);
The square brackets let you provide an arbitrary string to look up the name property in the object.

react native firestore. 'array-contains' query not working with number value

Have a strange problem with react-native-firebase library:
Steps:
Try to fetch data with the firestore:
await firestore().collection(collectionName)
.where(ConversationModel.refs.employees, 'array-contains', '646').get();
where 646 - element in array
When I use an array of strings, this code works as expected
But when I set the number value (646) and try to fetch the array of numbers - this code returns empty result.
Correct sample:
await firestore().collection(collectionName)
.where(ConversationModel.refs.employees, 'array-contains', '646').get();
Wrong sample:
await firestore().collection(collectionName)
.where(ConversationModel.refs.employees, 'array-contains', 646).get();
UPDATE: Fixed in 6.1.0 https://invertase.io/oss/react-native-firebase/releases/v6.1.0
The official documentation found here https://firebase.google.com/docs/firestore/query-data/queries says "You can use the array-contains operator to filter based on array values", I believe the key take away here is "values".
In the correct one you are using a string and in the wrong one you are using a Integer. It might then be that you have stored the values as Text string and not as Integers. Supported data types listed here https://firebase.google.com/docs/firestore/manage-data/data-types
Firestore queries are type-sensitive. If you want to get documents where the employees array contains the number 646, you need to build a query that checks for that number. So something like:
await firestore().collection(collectionName)
.where(ConversationModel.refs.employees, 'array-contains', 646).get();

Firestore data model is inconsistent

I'm trying to save some data in firestore, the data consists of events, each event has a date and each some attendees.
What I'm trying to do now is model it like this events/${eventDate}/${userEmail} and then I would set this with the user's data. However when I try to set this data I get an error saying that the segment number should be even.
When I added another segment in the path (which I didn't want to do):
events/${eventDate}/attendees/${userEmail} I was able to set the data but I wasn't able to retrieve it (trying to retrieve all attendees of a given event date.
// insertion - this worked after some tweaking
this.db.collection('pickups').doc(pickupDate).set({ [email]: userData})
// deletion (this doesn't work - expects even number of segments)
this.db.collection('pickups').doc(`${pickupDate}/${email}`).delete()
// retrieval (works)
this.db.collection('pickups').doc(pickupDate).valueChanges()
Current delete:
this.db.collection('pickups').doc(pickupDate).update({
[email]: firestore.FieldValue.delete()
})
What am I missing here? Isn't this supposed to be like regular JSON?
The path you're currently trying events/${eventDate}/${userEmail} is interpreted as a collection (events) then a document (eventDate) then another document (userEmail).
What you actually have is a collection, document within that collection, field within that document.
It looks like you're adding the email correctly (I would remove the brackets around the word email though), but trying to delete incorrectly. You delete fields like this:
var removeCapital = cityRef.update({
capital: firebase.firestore.FieldValue.delete()
});
You can see the documentation here: https://firebase.google.com/docs/firestore/manage-data/delete-data#fields
The delete may look like this:
this.db.collection('pickups').doc(pickupDate).update({
email: firebase.firestore.FieldValue.delete()
})
It sounds like what you're trying to do is delete a field out of a document. However, this code you have:
this.db.collection('pickups').doc(`${pickupDate}/${email}`).delete()
is trying to build a reference to a collection, then delete it. It's not correct to use collection() and doc() to reference fields in a document. They are just used to build references to documents and collections.
If you want to delete a field in a document, first build a reference to the document that contains the field:
const ref = this.db.collection('pickups').doc(pickupDate)
Then update the document to indicate that you want the field removed:
ref.update({ [email]: firebase.firestore.FieldValue.delete() }}
The way you reference delete() out of FieldValue is going to change based on how you have the SDK imported into your code.
See the documentation on deleting fields for more information.

Why graphQl returns "Unknown argument 'first' on field..." error when trying to slice on query?

I am trying to fetch first five items of a set. My query is following:
query sequence($id: String) {
sequence(id: $id) {
items(first:1) {
content
}
}
}
How ever, I get response
"Unknown argument \"first\" on field \"items\" of type \"Sequence\"."
As far as I understood from the docs this is how I am supposed to make query if I want to get a limited amount of items back.
Do I need to define the argument somewhere in the schema? How do I limit the amount of returned items properly?
All field arguments need to be defined in the schema, the default behaviour is for a field to accept no arguments.
You can define a first argument in your items field in your schema using syntax like this:
type Sequence {
items(first: Int): [Item]
}
(See: Example No. 120 in the spec.)

Firebase realtime database : how to check if child value exists

Given the document below.
website:{
uid1:{
foo:"bar",
username:"joff"
},
uid2:{
foo:"bar2",
username:"karla"
}
}
I am trying to check if the username already exist using the query below.
var ref = db.ref('website');
var queryString = 'joff';
ref.orderByChild('username').equalTo(queryString).once('value', function(snap){
if(snap.exists()){
// exists
return
}
console.log('available');
})
This approach is working without a problem, if I change the queryString accordingly I get the result that I want if it exists or not.
Firebase's default query limit is 100 and I can change it to my liking according to the documentation.
But what if I will query though a let's say 10,000 documents? I cant use paginated query here, because what if the query match is on the 2nd page? How do I handle such amount of data? Will it take too long before it respond? What is the right approach to do such query.
PS
I strictly need the data model to be the same as the given above.
Thanks in advance.
I thought that use of equalTo generated a "smart" query, and so the query limit wouldn't be factor in determining if record exists. I'm not positive though. Have you actually verified that having more than 100 records, with your 'joff` being at 100+ in the ordering, results in no match?
If that is the case (which would be very surprising), then you could probably restructure your query something like this:
ref.orderByChild('username').startAt(queryString).endAt(queryString).once('value', function(snap){
if(snap.exists()){
// exists
return
}
console.log('available');
})
... but again, I don't think that is required when using equalTo.

Categories

Resources