如何在couchdb中创建"like"过滤器视图

yud*_*uda 15 javascript couchdb

这是我在sql中需要的一个例子:

SELECT名称FROM使用WHERE名称LIKE %bro%

如何在couchdb中创建类似的视图?

nat*_*evw 14

简单的答案是CouchDB视图并不理想.

更复杂的答案是,这种类型的查询在典型的SQL引擎中往往效率非常低,因此如果您同意对任何解决方案进行权衡,那么CouchDB实际上具有让您选择权衡的好处.

1. SQL方式

当你这样做时SELECT ... WHERE name LIKE %bro%,我熟悉的所有SQL引擎都必须执行所谓的"全表扫描".这意味着服务器读取相关表中的每一行,然后强力扫描该字段以查看它是否匹配.

您可以使用$regex 运算符使用Mango查询在CouchDB 2.x中执行此操作.对于基本情况,查询看起来像这样:

{"selector":{
  "name": {
    "$regex": "bro"
  }
}}
Run Code Online (Sandbox Code Playgroud)

对于区分大小写等似乎没有任何公开选项,但您可以将其扩展为仅匹配开头/结尾或更复杂的模式.如果您还可以通过其他(可索引)字段运算符限制查询,则可能有助于提高性能.正如文档警告:

正则表达式不适用于索引,因此不应将它们用于过滤大型数据集.[...]

你也可以使用临时视图在CouchDB 1.x中进行全面扫描:

POST /some_database/_temp_view

{"map": "function (doc) { if (doc.name && doc.name.indexOf('bro') !== -1) emit(null); }"}
Run Code Online (Sandbox Code Playgroud)

这将查看数据库中的每个文档,并为您提供匹配文档的列表.您可以调整map函数以匹配文档类型,或者使用某个键进行排序emit(doc.timestamp)- 或者某些数据值对您的目的有用 - emit(null, doc.name).

2. "可用的磁盘空间量"方式

根据源数据大小,您可以创建一个索引,将每个可能的"内部字符串"作为其永久(磁盘上)视图键发出.也就是说,你会想要像"Dobros"这样的名字emit("dobros"); emit("obros"); emit("bros"); emit("ros"); emit("os"); emit("s");.然后,对于像'%bro%'这样的术语,您可以查询您的视图startkey="bro"&endkey="bro\uFFFF"以获取所有出现的查找字词.您的索引大约是文本内容平方的大小,但是如果您需要以比上面的完整数据库扫描更快的速度执行任何"查找字符串",并且可以使用此空间.尽管如此,为子字符串搜索设计的数据结构可以为您提供更好的服务.

这也给我们带来了......

3. 全文搜索方式

你可以使用CouchDB插件(couchdb-lucene现在通过Dreyfus/Clouseau for 2.x,ElasticSearch,SQLite的FTS)来为你的文档生成一个辅助的面向文本的索引.

请注意,大多数全文搜索索引自然不支持任意通配符前缀,可能出于类似的空间效率原因,如上所述.通常全文搜索并不意味着"暴力二元搜索",而是"字搜索".但是,YMMV,请查看全文引擎中可用的选项.

如果你真的不需要在字段中的任何地方找到"bro" ,你可以通过分割各种特定于语言环境的单词分隔符并省略这些"单词"来实现基本的"以X开头的单词"搜索和常规的CouchDB视图.作为你的视图键.这将比上述更有效,按比例缩放到索引的数据量.