Google Firestore:从属性值的子字符串查询(文本搜索)

16 浏览
0 Comments

Google Firestore:从属性值的子字符串查询(文本搜索)

我想添加一个简单的搜索字段,希望使用类似于

“collectionRef.where(\'name\', \'contains\', \'searchTerm\')”这样的东西。

我尝试使用“where(\'name\', \'==\', \'%searchTerm%\')”,但它没有返回任何结果。

admin 更改状态以发布 2023年5月22日
0
0 Comments

全文搜索、相关搜索和 Trigram 搜索!

更新 - 2/17/21 - 我创建了几个新的全文搜索选项。

有关详细信息,请参见 Code.Build


另外,旁注,dgraph 现在具有实时的 WebSockets ... 哇,从未见过这样的东西,真是太棒了!Cloud Dgraph - 太惊人了!


-- 原帖--

这里有几点注意事项:

1.) \uf8ff 的作用方式与 ~ 相同

2.) 您可以使用 where 子句或 start end 子句:

ref.orderBy('title').startAt(term).endAt(term + '~');

ref.where('title', '>=', term).where('title', '<=', term + '~');

完全相同

3.) 不,如果您在每种组合中反转 startAt()endAt(),它不会起作用。但是,您可以通过创建一个反向的第二个搜索字段并组合结果来实现相同的结果。

示例:首先,当创建字段时,必须保存字段的反向版本。像这样:

// collection
const postRef = db.collection('posts')
async function searchTitle(term) {
  // reverse term
  const termR = term.split("").reverse().join("");
  // define queries
  const titles = postRef.orderBy('title').startAt(term).endAt(term + '~').get();
  const titlesR = postRef.orderBy('titleRev').startAt(termR).endAt(termR + '~').get();
  // get queries
  const [titleSnap, titlesRSnap] = await Promise.all([
    titles,
    titlesR
  ]);
  return (titleSnap.docs).concat(titlesRSnap.docs);
}

这样,您可以搜索字符串字段的最后一个字母和第一个字母,但不能搜索任意中间字母或字母组。这更接近所需的结果。但是,当我们想要随机中间字母或单词时,这并不能帮助我们。此外,请记住保存所有小写字母或小写副本以供搜索,以便大小写不成为问题。

4.) 如果您只有几个单词,Ken Tan 的方法 将实现您想要的一切,或者至少在您稍微修改后可以实现。但是,仅具有一段文本的情况下,您将指数地创建超过 1MB 的数据,这超出了 firestore 的文档大小限制(我知道,我测试过了)。

5.) 如果你可以将array-contains(或一些形式的数组)与\uf8ff技巧相结合,你可能可以拥有一个不会达到极限的可行搜索结果。我尝试了所有组合,甚至使用映射,但没有用。如果有人能够解决这个问题,在这里发布一下。

6.) 如果你必须离开ALGOLIA和ELASTIC SEARCH,我完全不怪你,你可以在Google Cloud上使用mySQL、postSQL或neo4Js。它们都很容易设置,而且有免费的层。你需要一个云函数在onCreate()时保存数据,另一个onCall()函数用来搜索数据。简单……有点复杂。为什么不直接切换到mySQL呢?当然是实时数据!当有人为实时数据编写具有网络袜子的DGraph时,我会加入进来的!

Algolia和ElasticSearch是专门用于搜索的数据库,因此没有什么比它们更快的了……但你需要为此付费。Google,为什么你导引我们远离Google,而不像MongoDB无SQL那样允许搜索呢?

0
0 Comments

我赞同@Kuba的答案,但仍需要添加一个小改变,以使其完美地适用于按前缀搜索。以下是对我有效的方法:

搜索以名称queryText开头的记录

collectionRef
    .where('name', '>=', queryText)
    .where('name', '<=', queryText+ '\uf8ff')

查询中使用的字符\uf8ff是Unicode范围中非常高的代码点(它是专用区域[PUA]代码)。因为它在Unicode的大多数常规字符之后,所以查询匹配所有以queryText开头的值。

0