Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Autocomplete 使用Firebase自动完成_Autocomplete_Firebase - Fatal编程技术网

Autocomplete 使用Firebase自动完成

Autocomplete 使用Firebase自动完成,autocomplete,firebase,Autocomplete,Firebase,如何使用Firebase进行基本的自动完成/文本预览 例如,想象一个由Firebase支持的博客,博客作者可以用标签标记文章。当博主正在为一篇新文章添加标签时,如果他们能看到所有与他们输入的前几次击键匹配的现有标签,那将是很有帮助的。因此,如果“blog”、“black”、“blacking saddles”和“bulldogs”是标签,如果用户输入“bl”,他们会得到前三个标签,但不会得到“bulldogs” 我最初的想法是,我们可以用标记的优先级设置标记,并使用startAt,这样我们的查询

如何使用Firebase进行基本的自动完成/文本预览

例如,想象一个由Firebase支持的博客,博客作者可以用标签标记文章。当博主正在为一篇新文章添加标签时,如果他们能看到所有与他们输入的前几次击键匹配的现有标签,那将是很有帮助的。因此,如果“blog”、“black”、“blacking saddles”和“bulldogs”是标签,如果用户输入“bl”,他们会得到前三个标签,但不会得到“bulldogs”

我最初的想法是,我们可以用标记的优先级设置标记,并使用startAt,这样我们的查询看起来像:

fb.child('tags').startAt('bl').limitToFirst(5).once('value', function(snap) {
  console.log(snap.val()) 
});
但这也会让“斗牛犬”成为结果之一(不是世界末日,但也不是最好的)。使用startAt('bl')。endAt('bl')不返回任何结果。有没有其他方法可以做到这一点

(我知道其中一个选择是,我们可以使用搜索服务器,比如ElasticSearch,但我希望在Firebase中保留尽可能多的内容。)

编辑

正如加藤所说,这里有一个具体的例子。我们有20000名用户,他们的姓名存储如下:

/users/$userId/name

通常,用户会按名称查找另一个用户。当用户正在查找他们的好友时,我们需要一个下拉列表来填充一个以搜索者输入的字母开头的用户列表。因此,如果我输入“Ja”,我希望在下拉列表中看到“Jake Heller”、“Jake gyllenhal”、“Jack Donaghy”等

从Kato的评论中得到启发——解决这个问题的一种方法是为要搜索自动完成的字段设置优先级,并使用startAt()、limit()和客户端筛选仅返回所需的结果。由于Firebase区分大小写,因此您需要确保优先级和搜索词的大小写较低

这是一个粗略的示例,使用我在问题中列出的用户示例来演示这一点:

对于“ja”搜索,假设所有用户的优先级都设置为用户名的小写版本:

fb.child('users').
  startAt('ja'). // The user-inputted search
  limitToFirst(20).
  once('value', function(snap) {
    for(key in snap.val()){
      if(snap.val()[key].indexOf('ja') === 0) {
        console.log(snap.val()[key];
      }
    }
});
这应该只返回实际以“ja”开头的名称(即使Firebase实际按字母顺序在“ja”之后返回名称)

我选择使用limitToFirst(20)来保持较小的响应大小,因为实际上,自动完成下拉列表永远不需要超过20。可能有更好的方法来进行过滤,但这至少应该说明这个概念

希望这对别人有帮助!Firebase的人很可能有更好的答案


(请注意,这是非常有限的——如果有人搜索姓氏,它将不会返回他们所寻找的。因此,“最佳”答案可能是使用类似加藤的搜索后端。)

我觉得有一种比客户端过滤或黑客攻击更简单、更优雅的方法来实现这一点

通过将搜索键转换为其“Unicode”值并将其存储为优先级,您可以通过将该值递增1,按startAt()和endAt()进行搜索

var start = "ABA";

var pad = "AAAAAAAAAA";
start += pad.substring(0, pad.length - start.length);

var blob = new Blob([start]);

var reader = new FileReader();
reader.onload = function(e) {
    var typedArray = new Uint8Array(e.target.result);
    var array = Array.prototype.slice.call(typedArray);
    var priority = parseInt(array.join(""));
    console.log("Priority of", start, "is:", priority);
}
reader.readAsArrayBuffer(blob);
然后,通过将最后一个字符码增加1并进行相同的转换,您可以将搜索优先级限制为键“ABB”:

var limit = String.fromCharCode(start.charCodeAt(start.length -1) +1);
limit = start.substring(0, start.length -1) +limit;
“ABA…”到“ABB…”的优先级为:

开始:65666565650000

完:65666665650000


傻瓜

我知道这是一个老话题,但它仍然相关。根据Neil的上述回答,您可以更轻松地执行以下操作:

fb.child('tags').startAt(queryString).endAt(queryString + '\uf8ff').limit(5)

上面查询中使用的\uf8ff字符是一个非常高的代码点 在Unicode范围内。因为它在中的大多数常规字符之后 如果是Unicode,则查询将匹配以queryString开头的所有值


根据Jake和Matt的回答,sdk 3.1的更新版本。“限制”不再有效:

firebaseDb.ref('users')
    .orderByChild('name')
    .startAt(query)
    .endAt(`${query}\uf8ff`)
    .limitToFirst(5)
    .on('child_added', (child) => {
      console.log(
          {
            id: child.key,
            name: child.val().name
          }
      )
    })

我们这里说的是多少张唱片?我们是在实现谷歌搜索还是一个真实的客户端自动完成?好问题。对于我们考虑在上执行自动完成的某些操作,有200多万条记录。对于其他人来说,可能只有100个(网站上的不同标签)到20000个(网站上注册用户的名字)的数量级。不过,我想我知道你可能会这么做。我们完全可以在客户端执行startAt()和limit(),然后过滤掉错误的结果(如我的示例中的“bulldogs”)。我认为对于FB中任何大小和数量的对象,只要我们使用limit(),这应该是有效的(对吗?)。这不如让Firebase为我们处理所有事情,但仍然是一种选择。对于这样一个通用的集合,要以如此简单的格式回答这一问题将非常困难。如果你先提供一个具体的案例,我可以帮助你解决细节问题。你提到的每一个对于“最优秀”来说都可能是不同的。我们可以排除200万以上绝对是ElasticSearch/手电筒项目。500k或更少,我只需要抓取它们并过滤客户端。2万个名字是多少,可能是40万?在这里,我可能只是按照名字的第一个字母索引或排序,然后从那个里过滤客户端,根据需要进行优化。选择一个,我们就可以完成它。另外,请注意,您可以使用来获取ElasticSearch结果,但仍然只能与Firebase进行交互,从而使它保持简单。我同意您在这里所做的大部分工作。对于这种直接的内容搜索,ElasticSearch是最简单、可能也是最干净的答案。随着应用程序的成熟,它也会随着您的需求而增长。如果我们仅限于严格的客户端回答,我将从startAt()和limit()开始,就像您所做的那样简单。包含样式搜索可以通过简单地分页服务器数据并手动搜索来实现——对于名称这样的小数据集,这是一个缓慢但合理的过程。这对100k记录有效吗?有人尝试过这么多数据吗?虽然这个示例(以及文档链接)专门针对web上的Firebase,但是