【问题标题】:Searching in Firebase without server side code在没有服务器端代码的 Firebase 中搜索
【发布时间】:2016-02-25 07:57:31
【问题描述】:

我正在尝试从 Firebase 获取名称中包含给定字符串的所有用户。 例如,如果我有这些用户:

Devid, Andy, Bob

我想获取名称中包含“D”的所有用户,所以我希望结果如下:

Devid, Andy

这是我的 Firebase 目前的结构:

由于 Firebase 区分大小写,我创建了一个包含小写名称的属性 name_

使用 startAt 和 endAt 我可以获取名称以定义的字符串开头的所有用户

ref.orderByChild("name_").startAt(text).endAt(text+"\uf8ff").on('value', ...);

但这只会给我名称以给定字符串开头的用户,例如,如果文本是“D”,我会得到:

Devid

1) 目前我的查询的意思是,“给我所有 name_ 以给定字符串开头的用户”有没有办法让它意味着“给我所有用户的名字包含给定的字符串”? 编辑:否

Firebase 查询没有类似于全文搜索的功能 运营商。要完成这些,您要么必须集成一个 外部全文搜索引擎,还是搞个很精致的 自定义索引方案。 Firebase and indexing/search

2) 目前我不想拥有服务器端代码,有什么好的和有效的方式来实现自定义索引?

谢谢

【问题讨论】:

  • 使用正则表达式?
  • 遗憾的是 startAt/endAt 不支持正则表达式
  • 使用正则表达式时,不需要使用 startAt/endAt... 这就是重点
  • 你是对的,问题是我们只能使用 startAt/endAt/equalsTo 来做查询。这是文档firebase.com/docs/web/guide/…
  • Firebase 查询没有任何类似于全文搜索运算符的功能。要完成这些,您要么必须集成一个外部全文搜索引擎,要么提出一个非常复杂的自定义索引方案。以前有人问过这个问题,所以我会找到一个重复的。

标签: firebase firebase-realtime-database database nosql


【解决方案1】:

好的 - 目前的结构无法完全按照您的意愿行事。

但是这只是突然出现在我的脑海中:

users:
  user_1234
    first_name: "Devid"
    components:
       "D": true
       "e": true
       "v": true
       "i": true
       "d": true
  user_5678
    first_name: "Andy"
    components:
       "A": true
       "n": true
       "d": true
       "y": true
  user_1010
    first_name: "Bob"
    components:
       "B": true
       "o": true
       "b": true

这里有一些 ObjC 代码来实现它(并且已经过测试!)

Firebase *ref = [myRootRef childByAppendingPath:@"users"];

FQuery *q1 = [ref queryOrderedByChild:@"components/b"];
FQuery *q2 = [q1 queryEqualToValue:@1];

[q2 observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

    NSLog(@"%@", snapshot.value);

}];

此代码返回 Bob。

要获取所有“d”人,请将“components/b”更改为“components/d”

编辑:

您可以非常疯狂并添加更​​多组合以扩展您的搜索能力

users:
  user_1234
    first_name: "Devid"
    components:
       "D": true
       "e": true
       "v": true
       "i": true
       "d": true
       "De": true
       "Dev": true
       "Devi": true
       "Devid": true
       "ev": true
       "evi": true
       "evid": true
       ... etc

编写几行代码来迭代名称并写出组合非常简单。

显然,将所有名字读取到快照中,将它们转储到数组中并(在 ObjC 中)使用 NSPredicate 提取您需要的内容会更有效(如果您的数据集有限)。

【讨论】:

  • 感谢您的回复杰!我在想类似的事情。有没有办法使用这个解决方案来搜索像“De”这样的 2 个字符?
  • 我认为像 {"devid", "evid", "vid", "id", "d"} 这样的东西应该可以工作,我也在考虑这样的解决方案 {"d" :{“e”:{“v”:{“i”:{“d”:真}}}}}。问题是:1)这个解决方案有效吗?有没有办法告诉 Firebase 索引这些数据? (我必须研究 Firebase 中的索引是如何工作的)2)是否可以在 Firebase 查询中使用这些索引,这样我就不必将所有数据下载到客户端,而只需将搜索结果下载到客户端?
  • 1) 效率高吗?没有真正的方法来回答这个问题。这取决于您的数据集大小、搜索频率和许多其他因素。然而,虽然在视觉上它有点凌乱,但磁盘空间很便宜,所以它不应该成为问题。 2)索引,是的。请参阅 firebase 指南和示例。当您查询时,节点(或节点)中的所有数据都将包含在快照中,因此是的,它们被下载到客户端。数据的影响和数量将再次取决于您的数据集大小。
  • 杰伊的答案很好。我从没想过有人会认真对待我评论中的“精心设计的自定义索引方案”部分,但你肯定正朝着这个方向前进。请注意,您在此处构建的内容本质上是全文搜索引擎也将执行的操作,尽管它们使用专门的数据结构来存储搜索词。
  • 感谢两位的帮助!我决定接受这个答案,因为它提供了一个示例,说明如何在没有服务器端代码的情况下实现文本搜索,这就是问题的目的。自定义索引实现起来很有趣,但我可能会使用处理搜索的服务器端脚本。
【解决方案2】:

github中的oxyzen库做到了 假设您使用一些包装的 firebase 进行插入和更新

对于索引部分基本上是功能:

  1. JSON 对文档进行字符串化。
  2. 删除所有属性名称和 JSON 只保存数据(正则表达式)。
  3. 删除所有 xml 标记(因此也包括 html)和属性(记住旧指南,“数据不应在 xml 属性中”),如果存在 xml 或 html,则仅保留纯文本。
  4. 删除所有特殊字符并用空格替换(正则表达式)
  5. 用一个空格替换多个空格的所有实例(正则表达式)
  6. 拆分为空格和循环:
  7. 对于每个单词,在您的数据库中的某个索引结构中添加对文档的引用,基本上包含以单词命名的子项,而子项以“ref/inthedatabase/dockey”的转义版本命名
  8. 然后像普通的 firebase 应用程序那样插入文档

在 oxyzen 实现中,文档的后续更新实际上会读取索引并更新它,删除不再匹配的单词,并添加新单词。

随后的单词搜索可以轻松找到单词 child 中的文档。 使用 hits 实现多词搜索

【讨论】:

    猜你喜欢
    • 2017-05-11
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    相关资源
    最近更新 更多