【问题标题】:Firebase no index definedFirebase 未定义索引
【发布时间】:2015-03-08 18:43:49
【问题描述】:

我正在使用 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”的用户。

我的 Firebase 规则:

{
  "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)`,所以我希望有 1 个孩子?

【问题讨论】:

  • “没有任何成功”是什么意思?我添加了很多索引,它总是可以正常工作。你能展示你的规则的相关部分吗? (点击问题下方的编辑链接添加信息,不要将其放在评论中)
  • 请注意,命令是.indexOn,而不是您在上面键入的.indexOf。如果你在规则中犯了同样的错字,那确实是行不通的。
  • 我的意思是 .indexOn,对不起。我的问题是我不知道在哪里放置 .indexOn
  • 这就是为什么我要求您将规则添加到问题中。这也让你有机会修正你的错字。 :-)
  • 啊,好吧,我明白为什么没有创建您的索引了。我会为那个写第二个答案,因为我在最初的答案中强调的问题也很相关。

标签: javascript json firebase


【解决方案1】:

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

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

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

由于您正在收听child_added,您的函数将为符合您查询的每个用户调用一次。所以 forEach 在你的 sn-p 中对我没有任何意义。如果您想使用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

测试2

可以也使用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】:

    现在您添加了规则,很明显那里出了什么问题。

    这些是您当前的规则:

    {
      "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 需要在数据所在的级别定义?

    【讨论】:

    • 谢谢弗兰克·范·普菲伦!你帮了我很多!
    • 索引不应该在Users下更深一层吗?这就是我解释 Firebase 文档的方式
    • 不,它应该是我在示例中放置的位置。检查链接的文档页面和那里的数据:结构是 /dinosaurs/$dinosaur/heightheightlength.indexOn 位于 dinostaurs 如果您无法生成在您自己的用例中正确索引,请打开一个新问题并包含您的数据示例和您的(安全)规则。
    猜你喜欢
    • 2012-12-08
    • 2012-09-18
    • 1970-01-01
    • 2018-08-02
    • 2012-08-24
    • 2016-10-24
    • 2015-03-23
    • 2023-03-29
    • 2013-01-26
    相关资源
    最近更新 更多