Firebase数据库警告:“使用未指定的索引。考虑添加'”。indexOn“以获得更好的性能

时间:2018-01-06 15:38:52

标签: java android json firebase firebase-realtime-database

使用Firebase实时数据库运行我的Android应用时,我收到以下警告:

  

使用未指定的索引。考虑将“.indexOn”...添加到您的安全和Firebase数据库规则中以获得更好的性能

我完全理解这个警告。但我不知道如何让它变得更好。我真的只想查询索引字段!

这是我的DB:

{      
  "groupUsers" : {
    "g1" : {
      "u1" : "admin"
    },
    "g2" : {
      "u1" : "admin",
      "u2" : "readonly"
    }
  },
  "groups" : {    
    "g1" : {
      "areas" : {
        "a1" : {
          "groupId" : "g1",
          "name" : "My Group"
        }
      },
      "interests" : {
        "i1" : {
          "groupId" : "g1",
          "name" : "My Interest"
        }
      },
      "points" : {
        "p1" : {
          "address" : "First Street",
          "areaId" : "a1",
          "groupId" : "g1",
          "latitude" : -25,
          "longitude" : -55,
          "name" : "Harry"
        }
      },
      "properties" : {
        "name" : "My Group Name"
      },
      "waypoints" : {
        "w1" : {
          "areaId" : "a1",
          "groupId" : "g1"
        }
      }
    }
  }
  "users" : {
    "u1" : {
      "email" : "some@domain.com",
      "firstName" : "Peter",
      "lastName" : "Smith"
    },
    "u2" : {
      "email" : "other@email.com",
      "firstName" : "John",
      "lastName" : "Wayne"
    }
  }
}

这些是我的安全规则:

{
  "rules": {       
    "groups": {          
      "$groupId": {
        ".read":  "root.child('groupUsers').child($groupId).child(auth.uid).exists()",
        ".write": "! root.child('groupUsers').child($groupId).exists() || root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin'",
        "$child": {
          ".write": "root.child('groupUsers').child($groupId).child(auth.uid).exists() && root.child('groupUsers').child($groupId).child(auth.uid).val() !== 'readonly' && ($child === 'points' || $child === 'visits')"
        }
      },

      "areas": {        
        ".indexOn": ["groupId", "name"]
      },
        "waypoints": {
        ".indexOn": ["groupId", "areaId", "sequenceNumber"]
      },
      "interests": {
        ".indexOn": ["groupId", "rank", "name"]
      },
      "points": {        
        ".indexOn": ["groupId", "areaId", "name"]
      },
      "visits": {
        ".indexOn": ["groupId", "pointId", "interestId", "userId"] 
      }
    },
    "users": {
      ".read": "auth != null",
      "$userId": {        
        ".write": "auth != null && $userId === auth.uid && newData.val() != null",
        ".indexOn": ["email", "firstName", "lastName"]
      }
    },
    "groupUsers": {
      ".read": "auth != null",
      "$groupId": {
        ".write": "auth != null && (root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin' || !root.child('groupUsers').child($groupId).exists())"
      }
    }
  }
}

问题是groupUser结构。它具有组键作为属性名称。 我没有要索引的字段,因为我没有常量属性名称。 如何更改结构以使所有字段都可以编入索引并且我的所有规则仍然有效?

2 个答案:

答案 0 :(得分:1)

我不是Firebase的专家,但在我看来,您的安全规则存在问题。特别是在部分中,您引用名为 " name" 的字段作为索引,但此字段不是直接的组对象的字段。 '名称'是 属性 对象的字段,因此您的组配置应该是:

  

.indexOn":[" properties / name"]

OR

  

.indexOn":" properties / name"

正如您所看到的,Firebase保留了' /' 字符,可以在对象的嵌套字段中导航以用作索引。

如果默认情况下访问属性字段,这是FireBase的隐含特征,请跳过我的回复部分。

我认为如果我们要将关系对象(用户/组)表示为警告的来源,我们需要至少正确优化其余的对象索引,然后我们可以重新设计关系表稍微整合内部可索引字段。

实体 - 关系结构的优化:

对于Entity-Relation表groupUser,一个建议可能是您将其合并到Group表中。在组内添加groupUsers字段。该字段由一个数组组成,每个数组条目都是一个User对象。这种方法的唯一问题是你需要以某种方式指定用户和这些条目之间的外键关系(就像我们在关系表中那样),以便利用级联操作。示例更改:

    "groups" : {    
        "g1" : {
          "areas" : {
            "a1" : {
              "groupId" : "g1",
              "name" : "My Group"
            }
          },
          "groupUsers" : [
             {"userID" : "u1"},
             {"userID" : "u2"}],...
}

或使用非阵列解决方案:

    "groups" : {    
        "g1" : {
          "areas" : {
            "a1" : {
              "groupId" : "g1",
              "name" : "My Group"
            }
          },
          "groupUsers" : {
              "r1" : {"userID" : "u1"},
              "r2" : {"userID" : "u2"}
           },...
}

答案 1 :(得分:1)

尝试收到您的问题,我明白您没有设置索引的关键名称,根据documentation here我们可以在此使用".value"在值上添加索引

以下内容可能对您有用,在 groupUsers 中的用户角色级别添加.value,因为这似乎只是字符串值(用户角色)可以设置索引

"groupUsers": {
  ".read": "auth != null",
  "$groupId": {
    ".write": "auth != null && (root.child('groupUsers').child($groupId).child(auth.uid).val() === 'admin' || !root.child('groupUsers').child($groupId).exists())"
    ".indexOn": ".value"
  }
}