【问题标题】:Firebase: How to structure for Multiple WHERE IN QueryFirebase:如何为多个 WHERE IN 查询构建结构
【发布时间】:2017-07-31 14:59:45
【问题描述】:

我在我的小型副项目中使用 Firebase 已经将近一年了,我非常喜欢它。但由于单一 orderByChild() 的限制,它不能用于需要复杂查询的大型项目。

仍在考虑如何将 Firebase 用于多 where 子句场景。在我用 PHP 开发的一个主要项目中,我们有如下查询:

SELECT * 
FROM  `masterEvents` 
WHERE causeId IN ( 1, 2, 3, 4, 5, 6, 7, 8 ) 
AND timeId IN (1, 2, 3, 4)
AND localityID IN (1, 2, 3, 4, 5)

以上查询。过滤在特定地点发生、在特定时间段内发生并涵盖给定原因的事件。

  • 地区可以有 40 个
  • 原因大约有 20 个
  • 时间将是 21

解决方案 1: 将所有 3 个过滤器键作为子级

{
    "eventIndex": {
        "ev1": {
            "name": "Event 1",
            "location": 2,
            "cause": 3,
            "time": 5,
        },
        "ev2": {
            "name": "Event 2",
            "location": 5,
            "cause": 2,
            "time": 1,
        },
        "ev3": {
            "name": "Event 3",
            "location": 26,
            "cause": 12,
            "time": 18,
        }
    }
}

forEach(location in selectedLocationArray) {
    firebase.database().ref("eventIndex").orderByChild("location").equalTo(location).on("value", snap => {
        // loop through all events and filter them based on selectedCauseArray and selectedTimeArray
    });
}

解决方案 2: 节点路径中的 1 个过滤键和子节点的 2 个过滤键

{
    "eventIndex": {
        "location1": {
            "ev1": {
                "name": "Event 1",
                "cause": 2,
                "time": 1,
            },
            "ev2": {
                "name": "Event 2",
                "cause": 12,
                "time": 18,
            }
        },
        "location2": {
            "ev4": {
                "name": "Event 4",
                "cause": 2,
                "time": 1,
            }
        },
        "location3": {
            "ev8": {
                "name": "Event 9",
                "cause": 2,
                "time": 1,
            },
            "ev9": {
                "name": "Event 9",
                "cause": 12,
                "time": 18,
            }
        }
    }
}

forEach(location in selectedLocationArray) {
    forEach(cause in selectedCauseArray) {
        firebase.database().ref("eventIndex/location" + location).orderByChild("cause").equalTo(cause).on("value", snap => {
            // loop through all events and filter them based on selectedTimeArray
        });
    }
}

解决方案 3: 2 个过滤器键在节点路径中,1 个过滤器键作为子项

以上哪一项是我可以采用的高效解决方案?谢谢:-)

PS:代码可以被视为伪代码来给出逻辑的概念,而不是实际代码。

【问题讨论】:

    标签: firebase web firebase-realtime-database


    【解决方案1】:

    我发现过滤数据的最有效方法之一是将多个键组合或组合在一起。

    例如,在您的问题中提到的上述结构中,我将添加另一个名为“_idx_location_cause_time”的字段,它是按顺序排列的值的组合 - 位置、原因和时间。

    ...
    "ev1": {
        "name": "Event 1",
        "location": 2,
        "cause": 3,
        "time": 5,
        "_idx_location_cause_time" : "2_3_5"
    },
    ...
    

    现在我可以使用orderByChild 查询来过滤结果。也就是说,

    dbRef.orderByChild(_idx_location_cause_time).equalTo("2_3_5").once("value", ...);

    这是关于如何使用它来构造数据并相应地过滤它们的一般概念。您还可以将此技术与您在问题中提到的技术一起应用,以进一步简化您的过滤过程。

    在 Firebase 规则中使用 .indexOn 对其进行索引以提高查询性能也很重要。

    希望对您有所帮助!

    【讨论】:

    • 这个解决方案不需要多个复合键吗?因为您可以按不同的组合进行过滤
    • @AngularM 现在更好的解决方案是使用 Firestore 编写高级查询
    • 将我的firebase实时数据库移到那里容易吗
    猜你喜欢
    • 1970-01-01
    • 2020-12-31
    • 2019-11-10
    • 1970-01-01
    • 2020-08-27
    • 2021-05-18
    • 2010-11-16
    • 1970-01-01
    • 2017-06-11
    相关资源
    最近更新 更多