【问题标题】:Advanced multiple search query in FirebaseFirebase 中的高级多重搜索查询
【发布时间】:2016-12-12 08:54:57
【问题描述】:

这是我在“/articles”中的 Firebase 数据库,里面有很多文章。用户可以(使用他/她自己的文章)列出与某些条件相对应的其他文章。为了使文章通过查询测试,它必须是用户文章在“tradableCategories”中列出的类别,同时该文章还需要在其“tradableCategories”中包含用户文章的类别。

这是数据库结构:

"articles": {
  "article1": {
    "title": "Car",
    "category": "vehicles",
    "owner": "user1",
    "tradableCategories": {
      "furnishings": true,
      "other": true,
      "vehicles": true
    },
    "category_tradableCategories": {
      "vehicles_furnishings": true,
      "vehicles_other": true,
      "vehicles_vehicles": true
    }
  },
  "article2": {
    "title": "Bike",
    "category": "vehicles",
    "owner": "user2",
    "tradableCategories": {
      "furnishings": true,
      "other": true
      "vehicles": true,
    },
    "category_tradableCategories": {
      "vehicles_furnishings": true,
      "vehicles_other": true,
      "vehicles_vehicles": true
    }
  },
  "article2": {
    "title": "Couch",
    "category": "furnishings",
    "owner": "user2",
    "tradableCategories": {
      "furnishings": true,
      "other": true,
      "vehicles": true
    },
    "category_tradableCategories": {
      "furnishings_furnishings": true,
      "furnishings_other": true,
      "furnishings_vehicles": true
    }
  },
  ...
}

user1 拥有 article1,它想要查找家具、其他和车辆中的文章。符合条件的文章也要查找article1的设置类别。使用 SQL 可以轻松完成查询:

SELECT *
FROM articles
WHERE category = ’vehicles’ /* This is article1’s category */
  AND find_in_set(category, :tradableCategories) /* :tradableCategories is a stringified, comma-separated set of article1’s tradableCategories: “furnishings,other,vehicles” */
  AND NOT owner = ‘user1’

正如您在数据库结构中看到的那样。我已经包含了另一个名为“category_tradableCategories”的对象。我在 Stack Overflow 上看到了各种答案,这些答案解释了如何将两个条件合二为一来搜索项目。这本来可行,但意味着我必须启动 3 个 Firebase 查询,因为我无法在 tradableCategories 中组合三个(或更多)不同的类别。

恐怕这对 Firebase 来说太复杂了,但如果有任何有效的解决方案,我希望得到一些帮助。谢谢!

【问题讨论】:

    标签: firebase firebase-realtime-database nosql


    【解决方案1】:

    在关系数据库中,您通常首先定义数据模型以匹配您要存储的数据,然后为应用的用例编写查询。在 NoSQL 数据库中,您通常使用逆向逻辑:列出应用程序的用例,然后定义数据模型以匹配这些用例。

    如果 Firebase 的 API 不直接支持您要构建的查询,您通常需要更改/扩充您的数据模型以允许该查询。这将导致存储更多的数据和更复杂的更新,但优点是您拥有更快、更简单的读取操作。

    因此,在您的场景中:您需要当前用户不拥有的三个类别之一的文章列表。该要求的最直接映射是按字面意思存储该列表:

    user_articles
      $uid
        categories_1_2_3
          articlekey1: true
          articlekey2: true
    

    这将使查询变得微不足道:ref.child("user_articles").child(currentUser.uid).child(categories).on("child_added"...

    现在这可能使非规范化和重复有点过分了。对于每个用户/类别组合,我们需要一个单独的列表。因此,一篇包含 10 个用户的 3 个类别的文章最终会出现在 60 个列表中。

    您更有可能希望将这些文章按类别保存在所有用户的单个列表中。例如:

    articles_by_category_with_owner
      category_1
        articlekey1: uid1
        articlekey2: uid2
        articlekey3: uid1
      category_2
        articlekey1: uid1
        articlekey2: uid2
      category_3
        articlekey1: uid1
        articlekey3: uid1
    

    现在您可以使用ref.child("articles_by_category_with_owner").child(category).on("child_added"... 获取所有 category_1 的文章键,然后在客户端执行“不属于当前用户”的过滤。

    在上面的列表中,我还删除了多个类别。这确实意味着您需要为每个类别读取一个节点。但这实际上并没有您想象的那么慢,因为 Firebase 会通过管道处理这些请求(请参阅下面的链接)。

    进一步推荐阅读/查看:

    【讨论】:

    • 非常感谢您的详细解答!我对您的第二个示例有疑问。这仅列出每个类别中的可用文章。首先我必须查询这个,然后我必须查询每篇文章的实际对象(标题、描述等)。这可能会导致应用程序内的每个提要请求有 100 个查询。这样好吗?我希望尽可能少的查询以最小化成本。但是这个例子使它比我现在的更复杂(后端)。
    • 请阅读我链接的文档,因为它解释了这是 NoSQL 数据库(尤其是 Firebase)中的常用方法。毕竟,要进一步阅读,请参阅我关于为什么这些客户端连接没有您想象的那么慢的答案:stackoverflow.com/questions/35931526/…
    • 在那里阅读您的答案。也会读其他的。感谢您的帮助!我会把它标记为这个问题的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-10-21
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2016-03-27
    • 2014-06-08
    • 1970-01-01
    相关资源
    最近更新 更多