Firebase没有定义索引

时间:2015-01-10 15:03:16

标签: javascript json firebase

我正在使用Firebase检索用户的一些数据。 我需要使用(gameSearching = true)检索只有一个用户

我的数据如下:

Users
|
|_____ John
|        |___ name: John Farmer
|        |___ gameSearching: true
|
|_____ James
|        |___ name: James Smith
|        |___ gameSearching: false
|
|_____ Barbara
         |___ name: Barbara Smith
         |___ gameSearching: true

我正在运行此代码:

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});
            }
        }
    );


});

因为'data'有多个值,所以我使用'data.forEach'来分隔它们。在那之后我可以在'true'上设置'return',所以我只会通过'gameSearching:true'接收一个用户。

我的火力基地规则:

{
  "rules": {
    ".read": true,
    ".write": true,
    ".indexOn": "gameSearching"
  }
}

当我运行此代码时,我收到以下错误:

  

'未捕获错误:没有为gameSearching'

定义索引

我搜索过使用'.indexOn'设置'gameSearching'的索引,但没有任何成功。 https://www.firebase.com/docs/security/guide/indexing-data.html

有没有人有例子或解决方案?


编辑:

我现在得到以下代码:

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');
    });

我编辑了我的firebase规则:

{
"rules": {
    ".read": true,
    ".write": true,
    "Users": {
  ".indexOn": "gameSearching"
}
}

}

indexOn错误不再显示,所以这很好。但ref.orderByChild("gameSearching").equalTo(true).limitToFirst(1)将运行两次。我不知道怎么可能。我正在使用limitToFirst(1)`,所以我希望有一个孩子?

3 个答案:

答案 0 :(得分:14)

现在你已经添加了规则,很清楚那里有什么问题。

这些是您目前的规则:

{
  "rules": {
    ".read": true,
    ".write": true,
    ".indexOn": "gameSearching"
  }
}

因此,您允许每个人在整个Firebase上进行读写访问,并告诉它在gameSearching上添加索引。问题是您已经在顶层定义了索引,而不是在Firebase中需要的级别。

这是您当前的数据结构:

{
    "Score" : {
        "sam_lous" : {
            "score" : 2
        }
    },
    "Users" : {
        "hallo" : {
            "gameSearching" : true
        },
        "sam_lous" : {
            "gameSearching" : true
        },
        "test" : {
            "gameSearching" : false
        },
        "test2" : {
            "gameSearching" : true
        }
    }
}

gameSearching属性仅存在于Users节点的子节点下。这就是您应该定义.indexOn

的地方
{
  "rules": {
    ".read": true,
    ".write": true,
    "Users": {
      ".indexOn": "gameSearching"
    }
  }
}

这样,您的索引应该被创建(根据我的经验,它会在您保存规则时立即发生)并且错误/警告消息应该消失。但是为了解决这个问题,你还应该做出我在其他答案中所做的更改。

我必须承认,Firebase's documentation on indexing your data可以更明确地定义这些.indexOn规则。如果Firebase的某位人员正在阅读,您是否可以添加一些更好的示例,突出显示.indexOn需要在数据所在级别定义?

答案 1 :(得分:3)

您的查询对数据进行排序,但无法对其进行过滤。如果您将其更改为此,则查询将仅匹配正在搜索游戏的用户:

var query = ref.orderByChild("gameSearching").equalTo(true);

这大致转换为WHERE gameSearching = true的SQL,这是您在上一个问题中提到的。请注意,我调用了变量query,因为它表示对数据的查询。或者如果你想坚持使用SQL隐喻,它更类似于关系数据库中的VIEW。

由于您正在收听child_added,因此每个适合您查询的用户都会调用一次您的函数。因此,forEach在您的代码段中对我没有任何意义。如果您想使用forEach,您可以使用value事件一次性获得与查询匹配的所有用户:

var searchers = ref.orderByChild("gameSearching").equalTo(true);
searchers.on('value', function(searchersSnapshot) {
    searchersSnapshot.forEach(function(snapshot) {
        console.log(snapshot.key());
    });
});

目前会在Firebase上记录此内容:

  

     

sam_lous

     

TEST2

可以也使用child_added来完成同样的工作,但在这种情况下你不需要forEach

var searchers = ref.orderByChild("gameSearching").equalTo(true);
searchers.on('child_added', function(snapshot) {
    console.log(snapshot.key());
});

有趣的事实:虽然on('child_added'触发了缺失索引的Firebase警告,但on('value'却没有。但无论哪种方式:你应该真正添加索引,因为没有这种性能会随着你添加玩家而受到不可接受的影响。

由于您表明您只需要一个孩子,您还可以进一步限制查询,只为您提供第一个孩子:

var searchers = ref.orderByChild("gameSearching").equalTo(true).limitToFirst(1);

Firebase Web Guide的第2 - 5部分介绍了这些和许多其他操作。

答案 2 :(得分:-1)

child.on(“ child_added”,.... 将此行更改为 child.on(“ value”,