I'm using Firebase to retrieve some data of Users.
I need to retrieve only one User with (gameSearching = true
).
My data looks like:
Users
|
|_____ John
| |___ name: John Farmer
| |___ gameSearching: true
|
|_____ James
| |___ name: James Smith
| |___ gameSearching: false
|
|_____ Barbara
|___ name: Barbara Smith
|___ gameSearching: true
I'm running this code:
setData(('Users/' + you + '/'), {gameSearching: true});
var ref = new Firebase("https://grootproject.firebaseio.com/Users");
var child = ref.orderByChild("gameSearching");
child.on("child_added", function (data) {
var yourself = firebase.getAuth().password.email.split("@", 1)[0];
data.forEach(
function (childSnapshot) {
if (childSnapshot[i].val().gameSearching == true && childSnapshot[i].key() != yourself) {
var opponent = childSnapshot[i].key();
setData(('Users/' + opponent + '/'), {gameSearching: false});
setData(('Users/' + yourself + '/'), {gameSearching: false});
}
}
);
});
Because 'data' has multiple values, I use 'data.forEach' to separate them. After that point I can set a 'return' on 'true' so I only will recieve one User with 'gameSearching: true'.
My firebase rules:
{
"rules": {
".read": true,
".write": true,
".indexOn": "gameSearching"
}
}
When I run this code I get the following error:
'Uncaught Error: No index defined for gameSearching'
I have searched for setting a index on 'gameSearching' using '.indexOn' but not with any succes. https://www.firebase.com/docs/security/guide/indexing-data.html
Does anyone have a example or a solution?
Edit:
I now got the following code:
var ref = new Firebase("https://grootproject.firebaseio.com/Users");
ref.orderByChild("gameSearching").equalTo(true).limitToFirst(1).on("child_added", function (data) {
var yourself = firebase.getAuth().password.email.split("@", 1)[0];
var opponent = data.key();
console.log(opponent);
setData(('Users/' + opponent + '/'), {gameSearching: false});
setData(('Users/' + yourself + '/'), {gameSearching: false});
console.log('ja');
});
I edited my rules of my firebase:
{
"rules": {
".read": true,
".write": true,
"Users": {
".indexOn": "gameSearching"
}
}
}
The indexOn error wont show anymore, so that's great. But ref.orderByChild("gameSearching").equalTo(true).limitToFirst(1
) will runs twice. I don't know how that's possible. I'm using limitToFirst(1)`, so I expect 1 child?
Now that you added your rules, it is clear what is wrong there.
These are your current rules:
{
"rules": {
".read": true,
".write": true,
".indexOn": "gameSearching"
}
}
So you allow everyone read and write access on your entire Firebase and tell it to add an index on gameSearching
. The problem is that you've defined your index at the top-level, instead of at the level where it needs to be in your Firebase.
This is your current data structure:
{
"Score" : {
"sam_lous" : {
"score" : 2
}
},
"Users" : {
"hallo" : {
"gameSearching" : true
},
"sam_lous" : {
"gameSearching" : true
},
"test" : {
"gameSearching" : false
},
"test2" : {
"gameSearching" : true
}
}
}
The gameSearching
property exists only under children of the Users
node. So that is where you should define your .indexOn
:
{
"rules": {
".read": true,
".write": true,
"Users": {
".indexOn": "gameSearching"
}
}
}
With that, your index should be created (in my experience it happens straight away when you save your rules) and the error/warning message should disappear. But to fix the behavior, you should also make the changes that I put in my other answer.
I have to admit that Firebase's documentation on indexing your data, could be clearer on where you define these .indexOn
rules. If someone at Firebase is reading along, can you please add some better examples that highlight that .indexOn
needs to be defined at the level where the data resides?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With