In Firebase Firestore, I want to use orderBy twice. Do I need to create an index to speed up the query? - javascript

In Firebase Firestore, I want to use orderBy twice. Do I need to create an index to speed up the query?
For example:
Query query = fsDB.collection("users").document(currentUID).collection("received_messages")
.orderBy("messageSeen").orderBy("date");
There is no automatic Error message that shows up like when using ranges or "where".
Structure looks like:
received_messages
date: 01/02/99
messageSeen: true
from: keuajopdf315
Should I put an index on the collection "received messages" and the "messageSeen" and "date" fields to speed up the query?

When I try to run a query with two orderBy() clauses, I get an error:
The query requires an index. You can create it here: ...
After adding the index that is linked in the error message, I can then retrieve the documents ordered-by-state-then-by-index. See my working jsbin here: https://jsbin.com/rewujav/edit?js,console
docs.orderBy("state").orderBy("index").get().then(function(snapshot) {
snapshot.forEach((doc) => {
console.log(doc.id+": state="+doc.data().state+" index="+doc.data().index);
})
})

Related

Query stored values that contain specific string

I have a small realtime firebase database that's set up like this:
database
-messages
--XXXXXXXXXXXX
---id : "XXX-XXX"
---content : "Hello world!"
It's a very simple message system, the id field is basically a combination of users id from my mysql database. I'm trying to return all messages that match one of the ids, either sender or receiver. But I can't do it, seems like firebase only support exacts querys. Could you give me some guidanse?
Here's the code I'm working with
firebase.database().ref("messages").orderByChild("id").equalTo(userId).on("value", function(snapshot)
I'm looking for something like ".contains(userId)"
Firebase supports exact matches (with equalTo) and so-called prefix queries where the value starts with a certain value (by combining startAt and endAt). It does not support querying for values that end with a certain value.
I recommend keeping a mapping from each user IDs to their messages nodes, somewhere separately in their database.
So say that you have:
messages: {
"XXXXXXXXXXXX": {
id : "YYY-ZZZ",
content : "Hello world!"
}
}
You also have the following mappings:
userMessages: {
"YYY": {
"XXXXXXXXXXXX": true
},
"ZZZ": {
"XXXXXXXXXXXX": true
}
}
Now with this information you can look up the messages for each user based on their ID.
For more on the modeling of this type of data, I recommend:
Best way to manage Chat channels in Firebase
Many to Many relationship in Firebase
this artcle on NoSQL data modeling

Unable to Fetch filtered data from firebase on multiple values

I am trying to fetch data from firebase from messages table having a column 'email' and email equal to suppose "x#gmail.com" and "y#gmail.com". I need to fetch data if email equals to any of the two, but the query which i am using seems to be wrong.
also the messages need to sorted by time which is working.
var ref = db.collection('messages').orderBy('timestamp','desc')
var ref2 = ref.orderByChild('email').equalTo('x#gmail.com','y#gmail.com')
ref2.onSnapshot(snapshot => {setMessages(snapshot.docs.map(doc => ({id: doc.id, message : doc.data()})))});
Assuming you're using Firestore, what you want is an IN query. This allows you to specify up to 10 email addressses:
db.collection('messages')
.orderBy('timestamp','desc')
.where('email', 'in', ['x#gmail.com','y#gmail.com'])
For more on this, see the Firestore documentation on in, not-in, and array-contains-any conditions.

Firebase orderByChild with equalTo() doesn't work in javascript

I have tried to use .indexOn of firebase on field 'status' which is inside the child of 'BOUGHT_PRODUCT'.
But, when i run following query.
db.ref().child('BOUGHT_PRODUCT')
.orderByChild('status')
.equalTo('Service')
.on("value", function (snapshot) {
console.log(snapshot.val());
});
I get null snapshots.
Even, Firebase warning of index :
"#firebase/database: FIREBASE WARNING: Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "status" at /BOUGHT_PRODUCT to your security rules for better performance."
Firebase Data:
Index firebase:
Your help would be appreciated.
Firebase Database queries run against each child under the location where you run them. The field you order/filter on must be at a fixed path under each child. Since you run the query on /BOUGHT_PRODUCT, the database searches for /BOUGHT_PRODUCT/$uid/status. And since that property doesn't exist, there are no results matching the query.
In other words: your current data structure allows you to query a specific user for the status of their products, but not across all users. If you want to implement that use-case, you will need to create a data model that allows it, e.g. a single top-level list of product statuses.
Statuses
product1: "Service"
product2: "Service"
product3: "Something else"
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value

Firestore manual entry for indices?

I have the following query:
get invitations() {
return this.firestore.colWithIds$(`users/${this.authProvider.currentUserId}/meetings`, (ref) => {
return ref
.where(`participants.${this.authProvider.currentUserId}.invitation`, '==', 'pending')
.orderBy('createdAt', 'desc')
});
}
Everytime Firebase will generate an error that says: This query required an index and generates a link with the currentUserId in it. I add it to the console and everything works as expected..
However, this seems a bit too manual to maintain when users are registering. How can I generate a index that is dynamic and does not require manual entry every time a new user downloads my app?
The query you want to do, in the general case, is not possible in Cloud Firestore with your data structure.
You will quickly run into the limit of 200 composite indexes per database, probably around your 200th user:
https://firebase.google.com/docs/firestore/quotas#indexes

Mongodb mapReduce: query another database

I'm trying to write a mapReduce function for MongoDb, and have a problem trying to query data from a second MongoDb database within the reduce function. Heres an example of the code:
var reduceUsers = function(key, values) {
var reducedUser = {
uid: key,
count: 0,
extractBytes: 0
};
var secondDb = db.getSiblingDB("second");
....
}
When I try running the mapReduce I get the following error:
015-09-04T15:50:23.690+0100 E QUERY Error: map reduce failed:{
"errmsg" : "exception: ReferenceError: db is not defined\n
All the code is in a .js file and I run it thus:
> mongo mapReduceTest.js
MapReduce can not access global shell objects like db. A MapReduce job can only obtain data from the one collection it runs on. It can not be used to aggregate data from more than one collection (good try, but MongoDB simply does not do JOINs). Whatever you are trying to do: it won't work this way.
When you would like advise how to solve the actual problem which lead you to this solution attempt, please open a new question which explains in detail what you are trying to do.

Categories