Unity中Firebase实时数据库按名称或ID查询异常问题
Unity Firebase实时数据库按ID/产品名称查询问题解决
问题根源分析
- 数据结构不合理:你当前用数组存储产品,Firebase Realtime Database对数组的查询支持有限,数组会被自动转换为数字索引的对象,容易导致查询逻辑异常甚至崩溃。
- 类型不匹配:数据中
id是数字类型,但你的代码里EqualTo("1001")传的是字符串,类型不兼容会引发查询错误。 - 代码逻辑错误:回调里判断的是
player.Child("code"),但数据里对应的字段是id,属于字段名写错;同时直接查询根节点(GetReference(""))容易导致数据解析混乱。
最优解决方案
1. 调整Firebase数据结构(关键)
将数组改为键值对对象存储,既保留可查询的id和product_name字段,又兼容Firebase的查询机制:
"products": { "product_1001": { "id": 1001, "price": "265$", "product_name": "dell", "type": "monitor" }, "product_1002": { "id": 1002, "price": "320$", "product_name": "ibm", "type": "laptop" }, "product_1003": { "id": 1003, "price": "542$", "product_name": "hp", "type": "workstation" } }
2. 添加Firebase索引
在Firebase控制台的实时数据库规则中添加索引,确保查询高效执行:
{ "rules": { "products": { ".indexOn": ["id", "product_name"] } } }
3. 修正查询代码
按ID查询
public void GetProductById(int targetId) { // 指向products节点,避免直接查询根节点 var productsRef = FirebaseDatabase.DefaultInstance.GetReference("products"); // EqualTo传入数字类型,与数据中的id类型匹配 productsRef.OrderByChild("id").EqualTo(targetId).ValueChanged += OnProductByIdReceived; } private void OnProductByIdReceived(object sender, ValueChangedEventArgs e) { if (e.Snapshot.Exists) { foreach (var productSnapshot in e.Snapshot.Children) { string productName = productSnapshot.Child("product_name").GetValue(true).ToString(); Debug.Log($"找到产品:{productName}"); } } else { Debug.Log("未找到对应ID的产品"); } }
按产品名称查询
public void GetProductByName(string targetName) { var productsRef = FirebaseDatabase.DefaultInstance.GetReference("products"); productsRef.OrderByChild("product_name").EqualTo(targetName).ValueChanged += OnProductByNameReceived; } private void OnProductByNameReceived(object sender, ValueChangedEventArgs e) { if (e.Snapshot.Exists) { foreach (var productSnapshot in e.Snapshot.Children) { string productName = productSnapshot.Child("product_name").GetValue(true).ToString(); string price = productSnapshot.Child("price").GetValue(true).ToString(); Debug.Log($"找到产品:{productName},价格:{price}"); } } else { Debug.Log("未找到对应名称的产品"); } }
注意事项
- 调用查询后记得在合适的时机(比如场景销毁)移除事件监听,避免内存泄漏:
private void OnDestroy() { var productsRef = FirebaseDatabase.DefaultInstance.GetReference("products"); productsRef.ValueChanged -= OnProductByIdReceived; productsRef.ValueChanged -= OnProductByNameReceived; } - 如果你坚持使用原数组结构,必须确保根节点下只有产品数据,且
EqualTo传入的类型与id一致(数字1001而非字符串"1001"),但这种结构在数据量增大后查询性能会急剧下降,不推荐。
内容的提问来源于stack exchange,提问作者Kouibia Ibrahim
相关产品推荐
相关产品推荐

